diff --git a/instrumentation/opentelemetry_grpcbox/.gitignore b/instrumentation/opentelemetry_grpcbox/.gitignore new file mode 100644 index 0000000..f1c4554 --- /dev/null +++ b/instrumentation/opentelemetry_grpcbox/.gitignore @@ -0,0 +1,19 @@ +.rebar3 +_* +.eunit +*.o +*.beam +*.plt +*.swp +*.swo +.erlang.cookie +ebin +log +erl_crash.dump +.rebar +logs +_build +.idea +*.iml +rebar3.crashdump +*~ diff --git a/instrumentation/opentelemetry_grpcbox/LICENSE b/instrumentation/opentelemetry_grpcbox/LICENSE new file mode 100644 index 0000000..bf5e6d8 --- /dev/null +++ b/instrumentation/opentelemetry_grpcbox/LICENSE @@ -0,0 +1,191 @@ + 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 2022, Tristan Sloughter . + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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/instrumentation/opentelemetry_grpcbox/README.md b/instrumentation/opentelemetry_grpcbox/README.md new file mode 100644 index 0000000..7bb0f42 --- /dev/null +++ b/instrumentation/opentelemetry_grpcbox/README.md @@ -0,0 +1,35 @@ +opentelemetry_grpcbox +===== + +This [grpcbox](https://github.com/tsloughter/grpcbox) interceptor uses the +[OpenTelemetry](http://opentelemetry.io/) API to create Spans for outgoing and +incoming requests and propagates them as part of the gRPC metadata. + +### Server + +Configure as an interceptor: + +```erlang +#{service_protos => [route_guide_pb], + unary_interceptor => {otel_grpcbox_interceptor, unary}} +``` + +Or as a middleware in the chain interceptor: + +```erlang +#{service_protos => [route_guide_pb], + unary_interceptor => + grpcbox_chain_interceptor:unary([..., + fun otel_grpcbox_interceptor:unary/4, + ...])} +``` + +### Client + +Example in `sys.config` for setting up a [client +channel](https://grpc.io/docs/what-is-grpc/core-concepts/#channels): + +``` erlang +{client, #{channels => [{default_channel, [{http, "localhost", 8080, []}], + #{unary_interceptor => fun otel_grpcbox_interceptor:unary_client/7}}]}} +``` diff --git a/instrumentation/opentelemetry_grpcbox/rebar.config b/instrumentation/opentelemetry_grpcbox/rebar.config new file mode 100644 index 0000000..bf0e602 --- /dev/null +++ b/instrumentation/opentelemetry_grpcbox/rebar.config @@ -0,0 +1,26 @@ +{erl_opts, [debug_info]}. + +{deps, [grpcbox, + {opentelemetry_api, "~> 1.0"}]}. + +{project_plugins, [{rebar_covertool, "1.1.0"}, + {grpcbox_plugin, "~> 0.7.0"}]}. + +{profiles, + [{test, [{erl_opts, [nowarn_export_all]}, + + {grpc, [{protos, "test/otel_interceptor_SUITE_data"}, + {out_dir, "test"}, + {gpb_opts, [{o, "test"}, + {descriptor, true}, + {module_name_suffix, "_pb"}]}]}, + + {deps, [{opentelemetry, "~> 1.0"}, + jsx]}]}]}. + +{cover_enabled, true}. +{cover_opts, [verbose]}. +{cover_export_enabled, true}. +{covertool, [{coverdata_files, ["ct.coverdata"]}]}. + +{ct_opts, [{ct_hooks, [cth_surefire]}]}. diff --git a/instrumentation/opentelemetry_grpcbox/rebar.lock b/instrumentation/opentelemetry_grpcbox/rebar.lock new file mode 100644 index 0000000..4ba15f9 --- /dev/null +++ b/instrumentation/opentelemetry_grpcbox/rebar.lock @@ -0,0 +1,26 @@ +{"1.2.0", +[{<<"acceptor_pool">>,{pkg,<<"acceptor_pool">>,<<"1.0.0">>},1}, + {<<"chatterbox">>,{pkg,<<"ts_chatterbox">>,<<"0.11.0">>},1}, + {<<"ctx">>,{pkg,<<"ctx">>,<<"0.6.0">>},1}, + {<<"gproc">>,{pkg,<<"gproc">>,<<"0.8.0">>},1}, + {<<"grpcbox">>,{pkg,<<"grpcbox">>,<<"0.14.0">>},0}, + {<<"hpack">>,{pkg,<<"hpack_erl">>,<<"0.2.3">>},2}, + {<<"opentelemetry_api">>,{pkg,<<"opentelemetry_api">>,<<"1.0.2">>},0}]}. +[ +{pkg_hash,[ + {<<"acceptor_pool">>, <<"43C20D2ACAE35F0C2BCD64F9D2BDE267E459F0F3FD23DAB26485BF518C281B21">>}, + {<<"chatterbox">>, <<"B8F372C706023EB0DE5BF2976764EDB27C70FE67052C88C1F6A66B3A5626847F">>}, + {<<"ctx">>, <<"8FF88B70E6400C4DF90142E7F130625B82086077A45364A78D208ED3ED53C7FE">>}, + {<<"gproc">>, <<"CEA02C578589C61E5341FCE149EA36CCEF236CC2ECAC8691FBA408E7EA77EC2F">>}, + {<<"grpcbox">>, <<"3EB321BCD2275BAF8B54CF381FEB7B0559A50C02544DE28FDA039C7F2F9D1A7A">>}, + {<<"hpack">>, <<"17670F83FF984AE6CD74B1C456EDDE906D27FF013740EE4D9EFAA4F1BF999633">>}, + {<<"opentelemetry_api">>, <<"91353EE40583B1D4F07D7B13ED62642ABFEC6AAA0D8A2114F07EDAFB2DF781C5">>}]}, +{pkg_hash_ext,[ + {<<"acceptor_pool">>, <<"0CBCD83FDC8B9AD2EEE2067EF8B91A14858A5883CB7CD800E6FCD5803E158788">>}, + {<<"chatterbox">>, <<"722FE2BAD52913AB7E87D849FC6370375F0C961FFB2F0B5E6D647C9170C382A6">>}, + {<<"ctx">>, <<"A14ED2D1B67723DBEBBE423B28D7615EB0BDCBA6FF28F2D1F1B0A7E1D4AA5FC2">>}, + {<<"gproc">>, <<"580ADAFA56463B75263EF5A5DF4C86AF321F68694E7786CB057FD805D1E2A7DE">>}, + {<<"grpcbox">>, <<"E24159B7B6D3F9869BBE528845C0125FED2259366BA908FD04A1F45FE81D0660">>}, + {<<"hpack">>, <<"06F580167C4B8B8A6429040DF36CC93BBA6D571FAEAEC1B28816523379CBB23A">>}, + {<<"opentelemetry_api">>, <<"2A8247F85C44216B883900067478D59955D11E58E5CFCA7C884CD4F203ACE3AC">>}]} +]. diff --git a/instrumentation/opentelemetry_grpcbox/src/opentelemetry_grpcbox.app.src b/instrumentation/opentelemetry_grpcbox/src/opentelemetry_grpcbox.app.src new file mode 100644 index 0000000..7f26f53 --- /dev/null +++ b/instrumentation/opentelemetry_grpcbox/src/opentelemetry_grpcbox.app.src @@ -0,0 +1,16 @@ +{application, opentelemetry_grpcbox, + [{description, "grpcbox interceptor for OpenTelemetry instrumentation"}, + {vsn, "0.1.0"}, + {registered, []}, + {applications, + [kernel, + stdlib, + opentelemetry_api, + grpcbox + ]}, + {env,[]}, + {modules, []}, + + {licenses, ["Apache-2.0"]}, + {links, [{"GitHub", "https://github.com/open-telemetry/opentelemetry-erlang-contrib/tree/main/instrumentation/opentelemetry_grpcbox"}]} + ]}. diff --git a/instrumentation/opentelemetry_grpcbox/src/otel_grpcbox_interceptor.erl b/instrumentation/opentelemetry_grpcbox/src/otel_grpcbox_interceptor.erl new file mode 100644 index 0000000..8973395 --- /dev/null +++ b/instrumentation/opentelemetry_grpcbox/src/otel_grpcbox_interceptor.erl @@ -0,0 +1,79 @@ +%%%------------------------------------------------------------------------ +%% Copyright 2022, Tristan Sloughter +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. +%% +%% @doc grpcbox interceptor for tracing grpc client and server requests. +%% @end +%%%------------------------------------------------------------------------- +-module(otel_grpcbox_interceptor). + +-export([%% server side + unary/4, + stream/4, + + %% unary client interceptor + unary_client/7, + + %% client streaminig interceptors + new_stream/6, + send_msg/3, + recv_msg/3]). + +-include_lib("opentelemetry_api/include/otel_tracer.hrl"). + +unary_client(Ctx, _Channel, Handler, FullMethod, Input, _Def, _Options) -> + Metadata = otel_propagator_text_map:inject(opentelemetry:get_text_map_injector(), + #{}, + fun set_metadata/3), + Ctx1 = grpcbox_metadata:append_to_outgoing_ctx(Ctx, Metadata), + ?with_span(FullMethod, #{}, fun(_) -> + Handler(Ctx1, Input) + end). + +new_stream(Ctx, Channel, Path, Def, Streamer, Options) -> + {ok, S} = Streamer(Ctx, Channel, Path, Def, Options), + {ok, #{client_stream => S}}. + +send_msg(#{client_stream := ClientStream}, Streamer, Input) -> + Streamer(ClientStream, Input). + +recv_msg(#{client_stream := ClientStream}, Streamer, Input) -> + Streamer(ClientStream, Input). + +unary(Ctx, Message, _ServerInfo=#{full_method := FullMethod}, Handler) -> + otel_ctx_from_ctx(Ctx), + ?with_span(FullMethod, #{}, fun(_) -> + Handler(Ctx, Message) + end). + +stream(Ref, Stream, _ServerInfo=#{full_method := FullMethod}, Handler) -> + Ctx = grpcbox_stream:ctx(Stream), + otel_ctx_from_ctx(Ctx), + ?with_span(FullMethod, #{}, fun(_) -> + Handler(Ref, Stream) + end). + +%% + +otel_ctx_from_ctx(Ctx) -> + Metadata = grpcbox_metadata:from_incoming_ctx(Ctx), + otel_propagator_text_map:extract(opentelemetry:get_text_map_extractor(), + Metadata, + fun maps:keys/1, + fun get_metadata/2). + +get_metadata(Key, Metadata) -> + maps:get(Key, Metadata, undefined). + +set_metadata(Key, Value, Metadata) -> + Metadata#{Key => Value}. diff --git a/instrumentation/opentelemetry_grpcbox/test/otel_interceptor_SUITE.erl b/instrumentation/opentelemetry_grpcbox/test/otel_interceptor_SUITE.erl new file mode 100644 index 0000000..570f156 --- /dev/null +++ b/instrumentation/opentelemetry_grpcbox/test/otel_interceptor_SUITE.erl @@ -0,0 +1,59 @@ +-module(otel_interceptor_SUITE). +-compile(export_all). + +-include_lib("common_test/include/ct.hrl"). +-include_lib("stdlib/include/assert.hrl"). + +-include_lib("opentelemetry_api/include/otel_tracer.hrl"). + +all() -> + [trace_interceptor]. + +init_per_suite(Config) -> + application:load(grpcbox), + application:load(opentelemetry), + Config. + +end_per_suite(_Config) -> + ok. + +init_per_testcase(trace_interceptor, Config) -> + application:set_env(opentelemetry, processors, [{otel_batch_processor, #{exporter => undefined}}]), + application:set_env(grpcbox, client, + #{channels => [{default_channel, + [{http, "localhost", 8080, []}], + #{unary_interceptor => fun otel_grpcbox_interceptor:unary_client/7}}]}), + application:ensure_all_started(opentelemetry), + application:set_env(grpcbox, servers, + [#{grpc_opts => + #{service_protos => [route_guide_pb], + services => #{'routeguide.RouteGuide' => routeguide_route_guide}, + unary_interceptor => + grpcbox_chain_interceptor:unary([fun otel_grpcbox_interceptor:unary/4, + fun ?MODULE:trace_to_trailer/4])}}]), + application:ensure_all_started(grpcbox), + Config. + +%% include a trace context and test that it works by having a second interceptor add +%% the trace id from the context as a response trailer. +trace_interceptor(_Config) -> + Point = #{latitude => 409146138, longitude => -746188906}, + ?with_span(<<"grpc-client-call">>, #{}, + fun(_) -> + {_, _Feature, #{trailers := Trailers}} = + routeguide_route_guide_client:get_feature(Point), + SpanCtx = ?current_span_ctx, + BinTraceId = integer_to_binary(otel_span:trace_id(SpanCtx)), + ?assertEqual(BinTraceId, maps:get(<<"x-grpc-trace-id">>, Trailers)) + + end), + ok. + +%% + +trace_to_trailer(Ctx, Message, _ServerInfo, Handler) -> + SpanCtx = ?current_span_ctx, + BinTraceId = integer_to_binary(otel_span:trace_id(SpanCtx)), + Trailer = grpcbox_metadata:pairs([{<<"x-grpc-trace-id">>, BinTraceId}]), + Ctx1 = grpcbox_stream:add_trailers(Ctx, Trailer), + Handler(Ctx1, Message). diff --git a/instrumentation/opentelemetry_grpcbox/test/otel_interceptor_SUITE_data/route_guide.proto b/instrumentation/opentelemetry_grpcbox/test/otel_interceptor_SUITE_data/route_guide.proto new file mode 100644 index 0000000..fc6d4be --- /dev/null +++ b/instrumentation/opentelemetry_grpcbox/test/otel_interceptor_SUITE_data/route_guide.proto @@ -0,0 +1,120 @@ +// Copyright 2015 gRPC 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. + +syntax = "proto3"; + +option java_multiple_files = true; +option java_package = "io.grpc.examples.routeguide"; +option java_outer_classname = "RouteGuideProto"; + +package routeguide; + +// Interface exported by the server. +service RouteGuide { + // A simple RPC. + // + // Obtains the feature at a given position. + // + // A feature with an empty name is returned if there's no feature at the given + // position. + rpc GetFeature(Point) returns (Feature) {} + + // A server-to-client streaming RPC. + // + // Obtains the Features available within the given Rectangle. Results are + // streamed rather than returned at once (e.g. in a response message with a + // repeated field), as the rectangle may cover a large area and contain a + // huge number of features. + rpc ListFeatures(Rectangle) returns (stream Feature) {} + + // A client-to-server streaming RPC. + // + // Accepts a stream of Points on a route being traversed, returning a + // RouteSummary when traversal is completed. + rpc RecordRoute(stream Point) returns (RouteSummary) {} + + // A Bidirectional streaming RPC. + // + // Accepts a stream of RouteNotes sent while a route is being traversed, + // while receiving other RouteNotes (e.g. from other users). + rpc RouteChat(stream RouteNote) returns (stream RouteNote) {} + + // A simple RPC, which always generates error response. + rpc GenerateError(Empty) returns (Empty) {} + + // A simple RPC, which always generates error response. + rpc StreamingGenerateError(Empty) returns (stream Empty) {} +} + +// Empty message - use for RPCs without input or output. +message Empty { +} + +// Points are represented as latitude-longitude pairs in the E7 representation +// (degrees multiplied by 10**7 and rounded to the nearest integer). +// Latitudes should be in the range +/- 90 degrees and longitude should be in +// the range +/- 180 degrees (inclusive). +message Point { + int32 latitude = 1; + int32 longitude = 2; +} + +// A latitude-longitude rectangle, represented as two diagonally opposite +// points "lo" and "hi". +message Rectangle { + // One corner of the rectangle. + Point lo = 1; + + // The other corner of the rectangle. + Point hi = 2; +} + +// A feature names something at a given point. +// +// If a feature could not be named, the name is empty. +message Feature { + // The name of the feature. + string name = 1; + + // The point where the feature is detected. + Point location = 2; +} + +// A RouteNote is a message sent while at a given point. +message RouteNote { + // The location from which the message is sent. + Point location = 1; + + // The message to be sent. + string message = 2; +} + +// A RouteSummary is received in response to a RecordRoute rpc. +// +// It contains the number of individual points received, the number of +// detected features, and the total distance covered as the cumulative sum of +// the distance between each point. +message RouteSummary { + // The number of points received. + int32 point_count = 1; + + // The number of known features passed while traversing the route. + int32 feature_count = 2; + + // The distance covered in metres. + int32 distance = 3; + + // The duration of the traversal in seconds. + int32 elapsed_time = 4; +} diff --git a/instrumentation/opentelemetry_grpcbox/test/otel_interceptor_SUITE_data/route_guide_db.json b/instrumentation/opentelemetry_grpcbox/test/otel_interceptor_SUITE_data/route_guide_db.json new file mode 100644 index 0000000..9d6a980 --- /dev/null +++ b/instrumentation/opentelemetry_grpcbox/test/otel_interceptor_SUITE_data/route_guide_db.json @@ -0,0 +1,601 @@ +[{ + "location": { + "latitude": 407838351, + "longitude": -746143763 + }, + "name": "Patriots Path, Mendham, NJ 07945, USA" +}, { + "location": { + "latitude": 408122808, + "longitude": -743999179 + }, + "name": "101 New Jersey 10, Whippany, NJ 07981, USA" +}, { + "location": { + "latitude": 413628156, + "longitude": -749015468 + }, + "name": "U.S. 6, Shohola, PA 18458, USA" +}, { + "location": { + "latitude": 419999544, + "longitude": -740371136 + }, + "name": "5 Conners Road, Kingston, NY 12401, USA" +}, { + "location": { + "latitude": 414008389, + "longitude": -743951297 + }, + "name": "Mid Hudson Psychiatric Center, New Hampton, NY 10958, USA" +}, { + "location": { + "latitude": 419611318, + "longitude": -746524769 + }, + "name": "287 Flugertown Road, Livingston Manor, NY 12758, USA" +}, { + "location": { + "latitude": 406109563, + "longitude": -742186778 + }, + "name": "4001 Tremley Point Road, Linden, NJ 07036, USA" +}, { + "location": { + "latitude": 416802456, + "longitude": -742370183 + }, + "name": "352 South Mountain Road, Wallkill, NY 12589, USA" +}, { + "location": { + "latitude": 412950425, + "longitude": -741077389 + }, + "name": "Bailey Turn Road, Harriman, NY 10926, USA" +}, { + "location": { + "latitude": 412144655, + "longitude": -743949739 + }, + "name": "193-199 Wawayanda Road, Hewitt, NJ 07421, USA" +}, { + "location": { + "latitude": 415736605, + "longitude": -742847522 + }, + "name": "406-496 Ward Avenue, Pine Bush, NY 12566, USA" +}, { + "location": { + "latitude": 413843930, + "longitude": -740501726 + }, + "name": "162 Merrill Road, Highland Mills, NY 10930, USA" +}, { + "location": { + "latitude": 410873075, + "longitude": -744459023 + }, + "name": "Clinton Road, West Milford, NJ 07480, USA" +}, { + "location": { + "latitude": 412346009, + "longitude": -744026814 + }, + "name": "16 Old Brook Lane, Warwick, NY 10990, USA" +}, { + "location": { + "latitude": 402948455, + "longitude": -747903913 + }, + "name": "3 Drake Lane, Pennington, NJ 08534, USA" +}, { + "location": { + "latitude": 406337092, + "longitude": -740122226 + }, + "name": "6324 8th Avenue, Brooklyn, NY 11220, USA" +}, { + "location": { + "latitude": 406421967, + "longitude": -747727624 + }, + "name": "1 Merck Access Road, Whitehouse Station, NJ 08889, USA" +}, { + "location": { + "latitude": 416318082, + "longitude": -749677716 + }, + "name": "78-98 Schalck Road, Narrowsburg, NY 12764, USA" +}, { + "location": { + "latitude": 415301720, + "longitude": -748416257 + }, + "name": "282 Lakeview Drive Road, Highland Lake, NY 12743, USA" +}, { + "location": { + "latitude": 402647019, + "longitude": -747071791 + }, + "name": "330 Evelyn Avenue, Hamilton Township, NJ 08619, USA" +}, { + "location": { + "latitude": 412567807, + "longitude": -741058078 + }, + "name": "New York State Reference Route 987E, Southfields, NY 10975, USA" +}, { + "location": { + "latitude": 416855156, + "longitude": -744420597 + }, + "name": "103-271 Tempaloni Road, Ellenville, NY 12428, USA" +}, { + "location": { + "latitude": 404663628, + "longitude": -744820157 + }, + "name": "1300 Airport Road, North Brunswick Township, NJ 08902, USA" +}, { + "location": { + "latitude": 407113723, + "longitude": -749746483 + }, + "name": "" +}, { + "location": { + "latitude": 402133926, + "longitude": -743613249 + }, + "name": "" +}, { + "location": { + "latitude": 400273442, + "longitude": -741220915 + }, + "name": "" +}, { + "location": { + "latitude": 411236786, + "longitude": -744070769 + }, + "name": "" +}, { + "location": { + "latitude": 411633782, + "longitude": -746784970 + }, + "name": "211-225 Plains Road, Augusta, NJ 07822, USA" +}, { + "location": { + "latitude": 415830701, + "longitude": -742952812 + }, + "name": "" +}, { + "location": { + "latitude": 413447164, + "longitude": -748712898 + }, + "name": "165 Pedersen Ridge Road, Milford, PA 18337, USA" +}, { + "location": { + "latitude": 405047245, + "longitude": -749800722 + }, + "name": "100-122 Locktown Road, Frenchtown, NJ 08825, USA" +}, { + "location": { + "latitude": 418858923, + "longitude": -746156790 + }, + "name": "" +}, { + "location": { + "latitude": 417951888, + "longitude": -748484944 + }, + "name": "650-652 Willi Hill Road, Swan Lake, NY 12783, USA" +}, { + "location": { + "latitude": 407033786, + "longitude": -743977337 + }, + "name": "26 East 3rd Street, New Providence, NJ 07974, USA" +}, { + "location": { + "latitude": 417548014, + "longitude": -740075041 + }, + "name": "" +}, { + "location": { + "latitude": 410395868, + "longitude": -744972325 + }, + "name": "" +}, { + "location": { + "latitude": 404615353, + "longitude": -745129803 + }, + "name": "" +}, { + "location": { + "latitude": 406589790, + "longitude": -743560121 + }, + "name": "611 Lawrence Avenue, Westfield, NJ 07090, USA" +}, { + "location": { + "latitude": 414653148, + "longitude": -740477477 + }, + "name": "18 Lannis Avenue, New Windsor, NY 12553, USA" +}, { + "location": { + "latitude": 405957808, + "longitude": -743255336 + }, + "name": "82-104 Amherst Avenue, Colonia, NJ 07067, USA" +}, { + "location": { + "latitude": 411733589, + "longitude": -741648093 + }, + "name": "170 Seven Lakes Drive, Sloatsburg, NY 10974, USA" +}, { + "location": { + "latitude": 412676291, + "longitude": -742606606 + }, + "name": "1270 Lakes Road, Monroe, NY 10950, USA" +}, { + "location": { + "latitude": 409224445, + "longitude": -748286738 + }, + "name": "509-535 Alphano Road, Great Meadows, NJ 07838, USA" +}, { + "location": { + "latitude": 406523420, + "longitude": -742135517 + }, + "name": "652 Garden Street, Elizabeth, NJ 07202, USA" +}, { + "location": { + "latitude": 401827388, + "longitude": -740294537 + }, + "name": "349 Sea Spray Court, Neptune City, NJ 07753, USA" +}, { + "location": { + "latitude": 410564152, + "longitude": -743685054 + }, + "name": "13-17 Stanley Street, West Milford, NJ 07480, USA" +}, { + "location": { + "latitude": 408472324, + "longitude": -740726046 + }, + "name": "47 Industrial Avenue, Teterboro, NJ 07608, USA" +}, { + "location": { + "latitude": 412452168, + "longitude": -740214052 + }, + "name": "5 White Oak Lane, Stony Point, NY 10980, USA" +}, { + "location": { + "latitude": 409146138, + "longitude": -746188906 + }, + "name": "Berkshire Valley Management Area Trail, Jefferson, NJ, USA" +}, { + "location": { + "latitude": 404701380, + "longitude": -744781745 + }, + "name": "1007 Jersey Avenue, New Brunswick, NJ 08901, USA" +}, { + "location": { + "latitude": 409642566, + "longitude": -746017679 + }, + "name": "6 East Emerald Isle Drive, Lake Hopatcong, NJ 07849, USA" +}, { + "location": { + "latitude": 408031728, + "longitude": -748645385 + }, + "name": "1358-1474 New Jersey 57, Port Murray, NJ 07865, USA" +}, { + "location": { + "latitude": 413700272, + "longitude": -742135189 + }, + "name": "367 Prospect Road, Chester, NY 10918, USA" +}, { + "location": { + "latitude": 404310607, + "longitude": -740282632 + }, + "name": "10 Simon Lake Drive, Atlantic Highlands, NJ 07716, USA" +}, { + "location": { + "latitude": 409319800, + "longitude": -746201391 + }, + "name": "11 Ward Street, Mount Arlington, NJ 07856, USA" +}, { + "location": { + "latitude": 406685311, + "longitude": -742108603 + }, + "name": "300-398 Jefferson Avenue, Elizabeth, NJ 07201, USA" +}, { + "location": { + "latitude": 419018117, + "longitude": -749142781 + }, + "name": "43 Dreher Road, Roscoe, NY 12776, USA" +}, { + "location": { + "latitude": 412856162, + "longitude": -745148837 + }, + "name": "Swan Street, Pine Island, NY 10969, USA" +}, { + "location": { + "latitude": 416560744, + "longitude": -746721964 + }, + "name": "66 Pleasantview Avenue, Monticello, NY 12701, USA" +}, { + "location": { + "latitude": 405314270, + "longitude": -749836354 + }, + "name": "" +}, { + "location": { + "latitude": 414219548, + "longitude": -743327440 + }, + "name": "" +}, { + "location": { + "latitude": 415534177, + "longitude": -742900616 + }, + "name": "565 Winding Hills Road, Montgomery, NY 12549, USA" +}, { + "location": { + "latitude": 406898530, + "longitude": -749127080 + }, + "name": "231 Rocky Run Road, Glen Gardner, NJ 08826, USA" +}, { + "location": { + "latitude": 407586880, + "longitude": -741670168 + }, + "name": "100 Mount Pleasant Avenue, Newark, NJ 07104, USA" +}, { + "location": { + "latitude": 400106455, + "longitude": -742870190 + }, + "name": "517-521 Huntington Drive, Manchester Township, NJ 08759, USA" +}, { + "location": { + "latitude": 400066188, + "longitude": -746793294 + }, + "name": "" +}, { + "location": { + "latitude": 418803880, + "longitude": -744102673 + }, + "name": "40 Mountain Road, Napanoch, NY 12458, USA" +}, { + "location": { + "latitude": 414204288, + "longitude": -747895140 + }, + "name": "" +}, { + "location": { + "latitude": 414777405, + "longitude": -740615601 + }, + "name": "" +}, { + "location": { + "latitude": 415464475, + "longitude": -747175374 + }, + "name": "48 North Road, Forestburgh, NY 12777, USA" +}, { + "location": { + "latitude": 404062378, + "longitude": -746376177 + }, + "name": "" +}, { + "location": { + "latitude": 405688272, + "longitude": -749285130 + }, + "name": "" +}, { + "location": { + "latitude": 400342070, + "longitude": -748788996 + }, + "name": "" +}, { + "location": { + "latitude": 401809022, + "longitude": -744157964 + }, + "name": "" +}, { + "location": { + "latitude": 404226644, + "longitude": -740517141 + }, + "name": "9 Thompson Avenue, Leonardo, NJ 07737, USA" +}, { + "location": { + "latitude": 410322033, + "longitude": -747871659 + }, + "name": "" +}, { + "location": { + "latitude": 407100674, + "longitude": -747742727 + }, + "name": "" +}, { + "location": { + "latitude": 418811433, + "longitude": -741718005 + }, + "name": "213 Bush Road, Stone Ridge, NY 12484, USA" +}, { + "location": { + "latitude": 415034302, + "longitude": -743850945 + }, + "name": "" +}, { + "location": { + "latitude": 411349992, + "longitude": -743694161 + }, + "name": "" +}, { + "location": { + "latitude": 404839914, + "longitude": -744759616 + }, + "name": "1-17 Bergen Court, New Brunswick, NJ 08901, USA" +}, { + "location": { + "latitude": 414638017, + "longitude": -745957854 + }, + "name": "35 Oakland Valley Road, Cuddebackville, NY 12729, USA" +}, { + "location": { + "latitude": 412127800, + "longitude": -740173578 + }, + "name": "" +}, { + "location": { + "latitude": 401263460, + "longitude": -747964303 + }, + "name": "" +}, { + "location": { + "latitude": 412843391, + "longitude": -749086026 + }, + "name": "" +}, { + "location": { + "latitude": 418512773, + "longitude": -743067823 + }, + "name": "" +}, { + "location": { + "latitude": 404318328, + "longitude": -740835638 + }, + "name": "42-102 Main Street, Belford, NJ 07718, USA" +}, { + "location": { + "latitude": 419020746, + "longitude": -741172328 + }, + "name": "" +}, { + "location": { + "latitude": 404080723, + "longitude": -746119569 + }, + "name": "" +}, { + "location": { + "latitude": 401012643, + "longitude": -744035134 + }, + "name": "" +}, { + "location": { + "latitude": 404306372, + "longitude": -741079661 + }, + "name": "" +}, { + "location": { + "latitude": 403966326, + "longitude": -748519297 + }, + "name": "" +}, { + "location": { + "latitude": 405002031, + "longitude": -748407866 + }, + "name": "" +}, { + "location": { + "latitude": 409532885, + "longitude": -742200683 + }, + "name": "" +}, { + "location": { + "latitude": 416851321, + "longitude": -742674555 + }, + "name": "" +}, { + "location": { + "latitude": 406411633, + "longitude": -741722051 + }, + "name": "3387 Richmond Terrace, Staten Island, NY 10303, USA" +}, { + "location": { + "latitude": 413069058, + "longitude": -744597778 + }, + "name": "261 Van Sickle Road, Goshen, NY 10924, USA" +}, { + "location": { + "latitude": 418465462, + "longitude": -746859398 + }, + "name": "" +}, { + "location": { + "latitude": 411733222, + "longitude": -744228360 + }, + "name": "" +}, { + "location": { + "latitude": 410248224, + "longitude": -747127767 + }, + "name": "3 Hasta Way, Newton, NJ 07860, USA" +}] diff --git a/instrumentation/opentelemetry_grpcbox/test/route_guide_pb.erl b/instrumentation/opentelemetry_grpcbox/test/route_guide_pb.erl new file mode 100644 index 0000000..4fbfbf6 --- /dev/null +++ b/instrumentation/opentelemetry_grpcbox/test/route_guide_pb.erl @@ -0,0 +1,2728 @@ +%% -*- coding: utf-8 -*- +%% @private +%% Automatically generated, do not edit +%% Generated by gpb_compile version 4.7.3 +-module(route_guide_pb). + +-export([encode_msg/2, encode_msg/3]). +-export([decode_msg/2, decode_msg/3]). +-export([merge_msgs/3, merge_msgs/4]). +-export([verify_msg/2, verify_msg/3]). +-export([get_msg_defs/0]). +-export([get_msg_names/0]). +-export([get_group_names/0]). +-export([get_msg_or_group_names/0]). +-export([get_enum_names/0]). +-export([find_msg_def/1, fetch_msg_def/1]). +-export([find_enum_def/1, fetch_enum_def/1]). +-export([enum_symbol_by_value/2, enum_value_by_symbol/2]). +-export([get_service_names/0]). +-export([get_service_def/1]). +-export([get_rpc_names/1]). +-export([find_rpc_def/2, fetch_rpc_def/2]). +-export([fqbin_to_service_name/1]). +-export([service_name_to_fqbin/1]). +-export([fqbins_to_service_and_rpc_name/2]). +-export([service_and_rpc_name_to_fqbins/2]). +-export([fqbin_to_msg_name/1]). +-export([msg_name_to_fqbin/1]). +-export([fqbin_to_enum_name/1]). +-export([enum_name_to_fqbin/1]). +-export([get_package_name/0]). +-export([uses_packages/0]). +-export([source_basename/0]). +-export([get_all_source_basenames/0]). +-export([get_all_proto_names/0]). +-export([get_msg_containment/1]). +-export([get_pkg_containment/1]). +-export([get_service_containment/1]). +-export([get_rpc_containment/1]). +-export([get_enum_containment/1]). +-export([get_proto_by_msg_name_as_fqbin/1]). +-export([get_proto_by_service_name_as_fqbin/1]). +-export([get_proto_by_enum_name_as_fqbin/1]). +-export([get_protos_by_pkg_name_as_fqbin/1]). +-export([descriptor/0, descriptor/1]). +-export([gpb_version_as_string/0, gpb_version_as_list/0]). + + +%% enumerated types + +-export_type([]). + +%% message types +-type empty() :: + #{ + }. + +-type point() :: + #{latitude => integer(), % = 1, 32 bits + longitude => integer() % = 2, 32 bits + }. + +-type rectangle() :: + #{lo => point(), % = 1 + hi => point() % = 2 + }. + +-type feature() :: + #{name => iodata(), % = 1 + location => point() % = 2 + }. + +-type route_note() :: + #{location => point(), % = 1 + message => iodata() % = 2 + }. + +-type route_summary() :: + #{point_count => integer(), % = 1, 32 bits + feature_count => integer(), % = 2, 32 bits + distance => integer(), % = 3, 32 bits + elapsed_time => integer() % = 4, 32 bits + }. + +-export_type(['empty'/0, 'point'/0, 'rectangle'/0, 'feature'/0, 'route_note'/0, 'route_summary'/0]). + +-spec encode_msg(empty() | point() | rectangle() | feature() | route_note() | route_summary(), atom()) -> binary(). +encode_msg(Msg, MsgName) when is_atom(MsgName) -> + encode_msg(Msg, MsgName, []). + +-spec encode_msg(empty() | point() | rectangle() | feature() | route_note() | route_summary(), atom(), list()) -> binary(). +encode_msg(Msg, MsgName, Opts) -> + case proplists:get_bool(verify, Opts) of + true -> verify_msg(Msg, MsgName, Opts); + false -> ok + end, + TrUserData = proplists:get_value(user_data, Opts), + case MsgName of + empty -> + encode_msg_empty(id(Msg, TrUserData), TrUserData); + point -> + encode_msg_point(id(Msg, TrUserData), TrUserData); + rectangle -> + encode_msg_rectangle(id(Msg, TrUserData), TrUserData); + feature -> + encode_msg_feature(id(Msg, TrUserData), TrUserData); + route_note -> + encode_msg_route_note(id(Msg, TrUserData), TrUserData); + route_summary -> + encode_msg_route_summary(id(Msg, TrUserData), + TrUserData) + end. + + +encode_msg_empty(_Msg, _TrUserData) -> <<>>. + +encode_msg_point(Msg, TrUserData) -> + encode_msg_point(Msg, <<>>, TrUserData). + + +encode_msg_point(#{} = M, Bin, TrUserData) -> + B1 = case M of + #{latitude := F1} -> + begin + TrF1 = id(F1, TrUserData), + if TrF1 =:= 0 -> Bin; + true -> + e_type_int32(TrF1, <>, TrUserData) + end + end; + _ -> Bin + end, + case M of + #{longitude := F2} -> + begin + TrF2 = id(F2, TrUserData), + if TrF2 =:= 0 -> B1; + true -> + e_type_int32(TrF2, <>, TrUserData) + end + end; + _ -> B1 + end. + +encode_msg_rectangle(Msg, TrUserData) -> + encode_msg_rectangle(Msg, <<>>, TrUserData). + + +encode_msg_rectangle(#{} = M, Bin, TrUserData) -> + B1 = case M of + #{lo := F1} -> + begin + TrF1 = id(F1, TrUserData), + if TrF1 =:= undefined -> Bin; + true -> + e_mfield_rectangle_lo(TrF1, + <>, + TrUserData) + end + end; + _ -> Bin + end, + case M of + #{hi := F2} -> + begin + TrF2 = id(F2, TrUserData), + if TrF2 =:= undefined -> B1; + true -> + e_mfield_rectangle_hi(TrF2, + <>, + TrUserData) + end + end; + _ -> B1 + end. + +encode_msg_feature(Msg, TrUserData) -> + encode_msg_feature(Msg, <<>>, TrUserData). + + +encode_msg_feature(#{} = M, Bin, TrUserData) -> + B1 = case M of + #{name := F1} -> + begin + TrF1 = id(F1, TrUserData), + case is_empty_string(TrF1) of + true -> Bin; + false -> + e_type_string(TrF1, <>, TrUserData) + end + end; + _ -> Bin + end, + case M of + #{location := F2} -> + begin + TrF2 = id(F2, TrUserData), + if TrF2 =:= undefined -> B1; + true -> + e_mfield_feature_location(TrF2, + <>, + TrUserData) + end + end; + _ -> B1 + end. + +encode_msg_route_note(Msg, TrUserData) -> + encode_msg_route_note(Msg, <<>>, TrUserData). + + +encode_msg_route_note(#{} = M, Bin, TrUserData) -> + B1 = case M of + #{location := F1} -> + begin + TrF1 = id(F1, TrUserData), + if TrF1 =:= undefined -> Bin; + true -> + e_mfield_route_note_location(TrF1, + <>, + TrUserData) + end + end; + _ -> Bin + end, + case M of + #{message := F2} -> + begin + TrF2 = id(F2, TrUserData), + case is_empty_string(TrF2) of + true -> B1; + false -> + e_type_string(TrF2, <>, TrUserData) + end + end; + _ -> B1 + end. + +encode_msg_route_summary(Msg, TrUserData) -> + encode_msg_route_summary(Msg, <<>>, TrUserData). + + +encode_msg_route_summary(#{} = M, Bin, TrUserData) -> + B1 = case M of + #{point_count := F1} -> + begin + TrF1 = id(F1, TrUserData), + if TrF1 =:= 0 -> Bin; + true -> + e_type_int32(TrF1, <>, TrUserData) + end + end; + _ -> Bin + end, + B2 = case M of + #{feature_count := F2} -> + begin + TrF2 = id(F2, TrUserData), + if TrF2 =:= 0 -> B1; + true -> + e_type_int32(TrF2, <>, TrUserData) + end + end; + _ -> B1 + end, + B3 = case M of + #{distance := F3} -> + begin + TrF3 = id(F3, TrUserData), + if TrF3 =:= 0 -> B2; + true -> + e_type_int32(TrF3, <>, TrUserData) + end + end; + _ -> B2 + end, + case M of + #{elapsed_time := F4} -> + begin + TrF4 = id(F4, TrUserData), + if TrF4 =:= 0 -> B3; + true -> + e_type_int32(TrF4, <>, TrUserData) + end + end; + _ -> B3 + end. + +e_mfield_rectangle_lo(Msg, Bin, TrUserData) -> + SubBin = encode_msg_point(Msg, <<>>, TrUserData), + Bin2 = e_varint(byte_size(SubBin), Bin), + <>. + +e_mfield_rectangle_hi(Msg, Bin, TrUserData) -> + SubBin = encode_msg_point(Msg, <<>>, TrUserData), + Bin2 = e_varint(byte_size(SubBin), Bin), + <>. + +e_mfield_feature_location(Msg, Bin, TrUserData) -> + SubBin = encode_msg_point(Msg, <<>>, TrUserData), + Bin2 = e_varint(byte_size(SubBin), Bin), + <>. + +e_mfield_route_note_location(Msg, Bin, TrUserData) -> + SubBin = encode_msg_point(Msg, <<>>, TrUserData), + Bin2 = e_varint(byte_size(SubBin), Bin), + <>. + +-compile({nowarn_unused_function,e_type_sint/3}). +e_type_sint(Value, Bin, _TrUserData) when Value >= 0 -> + e_varint(Value * 2, Bin); +e_type_sint(Value, Bin, _TrUserData) -> + e_varint(Value * -2 - 1, Bin). + +-compile({nowarn_unused_function,e_type_int32/3}). +e_type_int32(Value, Bin, _TrUserData) + when 0 =< Value, Value =< 127 -> + <>; +e_type_int32(Value, Bin, _TrUserData) -> + <> = <>, + e_varint(N, Bin). + +-compile({nowarn_unused_function,e_type_int64/3}). +e_type_int64(Value, Bin, _TrUserData) + when 0 =< Value, Value =< 127 -> + <>; +e_type_int64(Value, Bin, _TrUserData) -> + <> = <>, + e_varint(N, Bin). + +-compile({nowarn_unused_function,e_type_bool/3}). +e_type_bool(true, Bin, _TrUserData) -> + <>; +e_type_bool(false, Bin, _TrUserData) -> + <>; +e_type_bool(1, Bin, _TrUserData) -> <>; +e_type_bool(0, Bin, _TrUserData) -> <>. + +-compile({nowarn_unused_function,e_type_string/3}). +e_type_string(S, Bin, _TrUserData) -> + Utf8 = unicode:characters_to_binary(S), + Bin2 = e_varint(byte_size(Utf8), Bin), + <>. + +-compile({nowarn_unused_function,e_type_bytes/3}). +e_type_bytes(Bytes, Bin, _TrUserData) + when is_binary(Bytes) -> + Bin2 = e_varint(byte_size(Bytes), Bin), + <>; +e_type_bytes(Bytes, Bin, _TrUserData) + when is_list(Bytes) -> + BytesBin = iolist_to_binary(Bytes), + Bin2 = e_varint(byte_size(BytesBin), Bin), + <>. + +-compile({nowarn_unused_function,e_type_fixed32/3}). +e_type_fixed32(Value, Bin, _TrUserData) -> + <>. + +-compile({nowarn_unused_function,e_type_sfixed32/3}). +e_type_sfixed32(Value, Bin, _TrUserData) -> + <>. + +-compile({nowarn_unused_function,e_type_fixed64/3}). +e_type_fixed64(Value, Bin, _TrUserData) -> + <>. + +-compile({nowarn_unused_function,e_type_sfixed64/3}). +e_type_sfixed64(Value, Bin, _TrUserData) -> + <>. + +-compile({nowarn_unused_function,e_type_float/3}). +e_type_float(V, Bin, _) when is_number(V) -> + <>; +e_type_float(infinity, Bin, _) -> + <>; +e_type_float('-infinity', Bin, _) -> + <>; +e_type_float(nan, Bin, _) -> + <>. + +-compile({nowarn_unused_function,e_type_double/3}). +e_type_double(V, Bin, _) when is_number(V) -> + <>; +e_type_double(infinity, Bin, _) -> + <>; +e_type_double('-infinity', Bin, _) -> + <>; +e_type_double(nan, Bin, _) -> + <>. + +-compile({nowarn_unused_function,e_varint/3}). +e_varint(N, Bin, _TrUserData) -> e_varint(N, Bin). + +-compile({nowarn_unused_function,e_varint/2}). +e_varint(N, Bin) when N =< 127 -> <>; +e_varint(N, Bin) -> + Bin2 = <>, + e_varint(N bsr 7, Bin2). + +is_empty_string("") -> true; +is_empty_string(<<>>) -> true; +is_empty_string(L) when is_list(L) -> + not string_has_chars(L); +is_empty_string(B) when is_binary(B) -> false. + +string_has_chars([C | _]) when is_integer(C) -> true; +string_has_chars([H | T]) -> + case string_has_chars(H) of + true -> true; + false -> string_has_chars(T) + end; +string_has_chars(B) + when is_binary(B), byte_size(B) =/= 0 -> + true; +string_has_chars(C) when is_integer(C) -> true; +string_has_chars(<<>>) -> false; +string_has_chars([]) -> false. + + +decode_msg(Bin, MsgName) when is_binary(Bin) -> + decode_msg(Bin, MsgName, []). + +decode_msg(Bin, MsgName, Opts) when is_binary(Bin) -> + TrUserData = proplists:get_value(user_data, Opts), + decode_msg_1_catch(Bin, MsgName, TrUserData). + +-ifdef('OTP_RELEASE'). +decode_msg_1_catch(Bin, MsgName, TrUserData) -> + try decode_msg_2_doit(MsgName, Bin, TrUserData) + catch Class:Reason:StackTrace -> error({gpb_error,{decoding_failure, {Bin, MsgName, {Class, Reason, StackTrace}}}}) + end. +-else. +decode_msg_1_catch(Bin, MsgName, TrUserData) -> + try decode_msg_2_doit(MsgName, Bin, TrUserData) + catch Class:Reason -> + StackTrace = erlang:get_stacktrace(), + error({gpb_error,{decoding_failure, {Bin, MsgName, {Class, Reason, StackTrace}}}}) + end. +-endif. + +decode_msg_2_doit(empty, Bin, TrUserData) -> + id(decode_msg_empty(Bin, TrUserData), TrUserData); +decode_msg_2_doit(point, Bin, TrUserData) -> + id(decode_msg_point(Bin, TrUserData), TrUserData); +decode_msg_2_doit(rectangle, Bin, TrUserData) -> + id(decode_msg_rectangle(Bin, TrUserData), TrUserData); +decode_msg_2_doit(feature, Bin, TrUserData) -> + id(decode_msg_feature(Bin, TrUserData), TrUserData); +decode_msg_2_doit(route_note, Bin, TrUserData) -> + id(decode_msg_route_note(Bin, TrUserData), TrUserData); +decode_msg_2_doit(route_summary, Bin, TrUserData) -> + id(decode_msg_route_summary(Bin, TrUserData), + TrUserData). + + + +decode_msg_empty(Bin, TrUserData) -> + dfp_read_field_def_empty(Bin, 0, 0, TrUserData). + +dfp_read_field_def_empty(<<>>, 0, 0, _) -> #{}; +dfp_read_field_def_empty(Other, Z1, Z2, TrUserData) -> + dg_read_field_def_empty(Other, Z1, Z2, TrUserData). + +dg_read_field_def_empty(<<1:1, X:7, Rest/binary>>, N, + Acc, TrUserData) + when N < 32 - 7 -> + dg_read_field_def_empty(Rest, + N + 7, + X bsl N + Acc, + TrUserData); +dg_read_field_def_empty(<<0:1, X:7, Rest/binary>>, N, + Acc, TrUserData) -> + Key = X bsl N + Acc, + case Key band 7 of + 0 -> skip_varint_empty(Rest, 0, 0, TrUserData); + 1 -> skip_64_empty(Rest, 0, 0, TrUserData); + 2 -> + skip_length_delimited_empty(Rest, 0, 0, TrUserData); + 3 -> skip_group_empty(Rest, Key bsr 3, 0, TrUserData); + 5 -> skip_32_empty(Rest, 0, 0, TrUserData) + end; +dg_read_field_def_empty(<<>>, 0, 0, _) -> #{}. + +skip_varint_empty(<<1:1, _:7, Rest/binary>>, Z1, Z2, + TrUserData) -> + skip_varint_empty(Rest, Z1, Z2, TrUserData); +skip_varint_empty(<<0:1, _:7, Rest/binary>>, Z1, Z2, + TrUserData) -> + dfp_read_field_def_empty(Rest, Z1, Z2, TrUserData). + +skip_length_delimited_empty(<<1:1, X:7, Rest/binary>>, + N, Acc, TrUserData) + when N < 57 -> + skip_length_delimited_empty(Rest, + N + 7, + X bsl N + Acc, + TrUserData); +skip_length_delimited_empty(<<0:1, X:7, Rest/binary>>, + N, Acc, TrUserData) -> + Length = X bsl N + Acc, + <<_:Length/binary, Rest2/binary>> = Rest, + dfp_read_field_def_empty(Rest2, 0, 0, TrUserData). + +skip_group_empty(Bin, FNum, Z2, TrUserData) -> + {_, Rest} = read_group(Bin, FNum), + dfp_read_field_def_empty(Rest, 0, Z2, TrUserData). + +skip_32_empty(<<_:32, Rest/binary>>, Z1, Z2, + TrUserData) -> + dfp_read_field_def_empty(Rest, Z1, Z2, TrUserData). + +skip_64_empty(<<_:64, Rest/binary>>, Z1, Z2, + TrUserData) -> + dfp_read_field_def_empty(Rest, Z1, Z2, TrUserData). + +decode_msg_point(Bin, TrUserData) -> + dfp_read_field_def_point(Bin, + 0, + 0, + id(0, TrUserData), + id(0, TrUserData), + TrUserData). + +dfp_read_field_def_point(<<8, Rest/binary>>, Z1, Z2, + F@_1, F@_2, TrUserData) -> + d_field_point_latitude(Rest, + Z1, + Z2, + F@_1, + F@_2, + TrUserData); +dfp_read_field_def_point(<<16, Rest/binary>>, Z1, Z2, + F@_1, F@_2, TrUserData) -> + d_field_point_longitude(Rest, + Z1, + Z2, + F@_1, + F@_2, + TrUserData); +dfp_read_field_def_point(<<>>, 0, 0, F@_1, F@_2, _) -> + #{latitude => F@_1, longitude => F@_2}; +dfp_read_field_def_point(Other, Z1, Z2, F@_1, F@_2, + TrUserData) -> + dg_read_field_def_point(Other, + Z1, + Z2, + F@_1, + F@_2, + TrUserData). + +dg_read_field_def_point(<<1:1, X:7, Rest/binary>>, N, + Acc, F@_1, F@_2, TrUserData) + when N < 32 - 7 -> + dg_read_field_def_point(Rest, + N + 7, + X bsl N + Acc, + F@_1, + F@_2, + TrUserData); +dg_read_field_def_point(<<0:1, X:7, Rest/binary>>, N, + Acc, F@_1, F@_2, TrUserData) -> + Key = X bsl N + Acc, + case Key of + 8 -> + d_field_point_latitude(Rest, + 0, + 0, + F@_1, + F@_2, + TrUserData); + 16 -> + d_field_point_longitude(Rest, + 0, + 0, + F@_1, + F@_2, + TrUserData); + _ -> + case Key band 7 of + 0 -> + skip_varint_point(Rest, 0, 0, F@_1, F@_2, TrUserData); + 1 -> skip_64_point(Rest, 0, 0, F@_1, F@_2, TrUserData); + 2 -> + skip_length_delimited_point(Rest, + 0, + 0, + F@_1, + F@_2, + TrUserData); + 3 -> + skip_group_point(Rest, + Key bsr 3, + 0, + F@_1, + F@_2, + TrUserData); + 5 -> skip_32_point(Rest, 0, 0, F@_1, F@_2, TrUserData) + end + end; +dg_read_field_def_point(<<>>, 0, 0, F@_1, F@_2, _) -> + #{latitude => F@_1, longitude => F@_2}. + +d_field_point_latitude(<<1:1, X:7, Rest/binary>>, N, + Acc, F@_1, F@_2, TrUserData) + when N < 57 -> + d_field_point_latitude(Rest, + N + 7, + X bsl N + Acc, + F@_1, + F@_2, + TrUserData); +d_field_point_latitude(<<0:1, X:7, Rest/binary>>, N, + Acc, _, F@_2, TrUserData) -> + {NewFValue, RestF} = {begin + <> = <<(X bsl N + + Acc):32/unsigned-native>>, + id(Res, TrUserData) + end, + Rest}, + dfp_read_field_def_point(RestF, + 0, + 0, + NewFValue, + F@_2, + TrUserData). + +d_field_point_longitude(<<1:1, X:7, Rest/binary>>, N, + Acc, F@_1, F@_2, TrUserData) + when N < 57 -> + d_field_point_longitude(Rest, + N + 7, + X bsl N + Acc, + F@_1, + F@_2, + TrUserData); +d_field_point_longitude(<<0:1, X:7, Rest/binary>>, N, + Acc, F@_1, _, TrUserData) -> + {NewFValue, RestF} = {begin + <> = <<(X bsl N + + Acc):32/unsigned-native>>, + id(Res, TrUserData) + end, + Rest}, + dfp_read_field_def_point(RestF, + 0, + 0, + F@_1, + NewFValue, + TrUserData). + +skip_varint_point(<<1:1, _:7, Rest/binary>>, Z1, Z2, + F@_1, F@_2, TrUserData) -> + skip_varint_point(Rest, Z1, Z2, F@_1, F@_2, TrUserData); +skip_varint_point(<<0:1, _:7, Rest/binary>>, Z1, Z2, + F@_1, F@_2, TrUserData) -> + dfp_read_field_def_point(Rest, + Z1, + Z2, + F@_1, + F@_2, + TrUserData). + +skip_length_delimited_point(<<1:1, X:7, Rest/binary>>, + N, Acc, F@_1, F@_2, TrUserData) + when N < 57 -> + skip_length_delimited_point(Rest, + N + 7, + X bsl N + Acc, + F@_1, + F@_2, + TrUserData); +skip_length_delimited_point(<<0:1, X:7, Rest/binary>>, + N, Acc, F@_1, F@_2, TrUserData) -> + Length = X bsl N + Acc, + <<_:Length/binary, Rest2/binary>> = Rest, + dfp_read_field_def_point(Rest2, + 0, + 0, + F@_1, + F@_2, + TrUserData). + +skip_group_point(Bin, FNum, Z2, F@_1, F@_2, + TrUserData) -> + {_, Rest} = read_group(Bin, FNum), + dfp_read_field_def_point(Rest, + 0, + Z2, + F@_1, + F@_2, + TrUserData). + +skip_32_point(<<_:32, Rest/binary>>, Z1, Z2, F@_1, F@_2, + TrUserData) -> + dfp_read_field_def_point(Rest, + Z1, + Z2, + F@_1, + F@_2, + TrUserData). + +skip_64_point(<<_:64, Rest/binary>>, Z1, Z2, F@_1, F@_2, + TrUserData) -> + dfp_read_field_def_point(Rest, + Z1, + Z2, + F@_1, + F@_2, + TrUserData). + +decode_msg_rectangle(Bin, TrUserData) -> + dfp_read_field_def_rectangle(Bin, + 0, + 0, + id('$undef', TrUserData), + id('$undef', TrUserData), + TrUserData). + +dfp_read_field_def_rectangle(<<10, Rest/binary>>, Z1, + Z2, F@_1, F@_2, TrUserData) -> + d_field_rectangle_lo(Rest, + Z1, + Z2, + F@_1, + F@_2, + TrUserData); +dfp_read_field_def_rectangle(<<18, Rest/binary>>, Z1, + Z2, F@_1, F@_2, TrUserData) -> + d_field_rectangle_hi(Rest, + Z1, + Z2, + F@_1, + F@_2, + TrUserData); +dfp_read_field_def_rectangle(<<>>, 0, 0, F@_1, F@_2, + _) -> + S1 = #{}, + S2 = if F@_1 == '$undef' -> S1; + true -> S1#{lo => F@_1} + end, + if F@_2 == '$undef' -> S2; + true -> S2#{hi => F@_2} + end; +dfp_read_field_def_rectangle(Other, Z1, Z2, F@_1, F@_2, + TrUserData) -> + dg_read_field_def_rectangle(Other, + Z1, + Z2, + F@_1, + F@_2, + TrUserData). + +dg_read_field_def_rectangle(<<1:1, X:7, Rest/binary>>, + N, Acc, F@_1, F@_2, TrUserData) + when N < 32 - 7 -> + dg_read_field_def_rectangle(Rest, + N + 7, + X bsl N + Acc, + F@_1, + F@_2, + TrUserData); +dg_read_field_def_rectangle(<<0:1, X:7, Rest/binary>>, + N, Acc, F@_1, F@_2, TrUserData) -> + Key = X bsl N + Acc, + case Key of + 10 -> + d_field_rectangle_lo(Rest, + 0, + 0, + F@_1, + F@_2, + TrUserData); + 18 -> + d_field_rectangle_hi(Rest, + 0, + 0, + F@_1, + F@_2, + TrUserData); + _ -> + case Key band 7 of + 0 -> + skip_varint_rectangle(Rest, + 0, + 0, + F@_1, + F@_2, + TrUserData); + 1 -> + skip_64_rectangle(Rest, 0, 0, F@_1, F@_2, TrUserData); + 2 -> + skip_length_delimited_rectangle(Rest, + 0, + 0, + F@_1, + F@_2, + TrUserData); + 3 -> + skip_group_rectangle(Rest, + Key bsr 3, + 0, + F@_1, + F@_2, + TrUserData); + 5 -> + skip_32_rectangle(Rest, 0, 0, F@_1, F@_2, TrUserData) + end + end; +dg_read_field_def_rectangle(<<>>, 0, 0, F@_1, F@_2, + _) -> + S1 = #{}, + S2 = if F@_1 == '$undef' -> S1; + true -> S1#{lo => F@_1} + end, + if F@_2 == '$undef' -> S2; + true -> S2#{hi => F@_2} + end. + +d_field_rectangle_lo(<<1:1, X:7, Rest/binary>>, N, Acc, + F@_1, F@_2, TrUserData) + when N < 57 -> + d_field_rectangle_lo(Rest, + N + 7, + X bsl N + Acc, + F@_1, + F@_2, + TrUserData); +d_field_rectangle_lo(<<0:1, X:7, Rest/binary>>, N, Acc, + Prev, F@_2, TrUserData) -> + {NewFValue, RestF} = begin + Len = X bsl N + Acc, + <> = Rest, + {id(decode_msg_point(Bs, TrUserData), TrUserData), + Rest2} + end, + dfp_read_field_def_rectangle(RestF, + 0, + 0, + if Prev == '$undef' -> NewFValue; + true -> + merge_msg_point(Prev, + NewFValue, + TrUserData) + end, + F@_2, + TrUserData). + +d_field_rectangle_hi(<<1:1, X:7, Rest/binary>>, N, Acc, + F@_1, F@_2, TrUserData) + when N < 57 -> + d_field_rectangle_hi(Rest, + N + 7, + X bsl N + Acc, + F@_1, + F@_2, + TrUserData); +d_field_rectangle_hi(<<0:1, X:7, Rest/binary>>, N, Acc, + F@_1, Prev, TrUserData) -> + {NewFValue, RestF} = begin + Len = X bsl N + Acc, + <> = Rest, + {id(decode_msg_point(Bs, TrUserData), TrUserData), + Rest2} + end, + dfp_read_field_def_rectangle(RestF, + 0, + 0, + F@_1, + if Prev == '$undef' -> NewFValue; + true -> + merge_msg_point(Prev, + NewFValue, + TrUserData) + end, + TrUserData). + +skip_varint_rectangle(<<1:1, _:7, Rest/binary>>, Z1, Z2, + F@_1, F@_2, TrUserData) -> + skip_varint_rectangle(Rest, + Z1, + Z2, + F@_1, + F@_2, + TrUserData); +skip_varint_rectangle(<<0:1, _:7, Rest/binary>>, Z1, Z2, + F@_1, F@_2, TrUserData) -> + dfp_read_field_def_rectangle(Rest, + Z1, + Z2, + F@_1, + F@_2, + TrUserData). + +skip_length_delimited_rectangle(<<1:1, X:7, + Rest/binary>>, + N, Acc, F@_1, F@_2, TrUserData) + when N < 57 -> + skip_length_delimited_rectangle(Rest, + N + 7, + X bsl N + Acc, + F@_1, + F@_2, + TrUserData); +skip_length_delimited_rectangle(<<0:1, X:7, + Rest/binary>>, + N, Acc, F@_1, F@_2, TrUserData) -> + Length = X bsl N + Acc, + <<_:Length/binary, Rest2/binary>> = Rest, + dfp_read_field_def_rectangle(Rest2, + 0, + 0, + F@_1, + F@_2, + TrUserData). + +skip_group_rectangle(Bin, FNum, Z2, F@_1, F@_2, + TrUserData) -> + {_, Rest} = read_group(Bin, FNum), + dfp_read_field_def_rectangle(Rest, + 0, + Z2, + F@_1, + F@_2, + TrUserData). + +skip_32_rectangle(<<_:32, Rest/binary>>, Z1, Z2, F@_1, + F@_2, TrUserData) -> + dfp_read_field_def_rectangle(Rest, + Z1, + Z2, + F@_1, + F@_2, + TrUserData). + +skip_64_rectangle(<<_:64, Rest/binary>>, Z1, Z2, F@_1, + F@_2, TrUserData) -> + dfp_read_field_def_rectangle(Rest, + Z1, + Z2, + F@_1, + F@_2, + TrUserData). + +decode_msg_feature(Bin, TrUserData) -> + dfp_read_field_def_feature(Bin, + 0, + 0, + id(<<>>, TrUserData), + id('$undef', TrUserData), + TrUserData). + +dfp_read_field_def_feature(<<10, Rest/binary>>, Z1, Z2, + F@_1, F@_2, TrUserData) -> + d_field_feature_name(Rest, + Z1, + Z2, + F@_1, + F@_2, + TrUserData); +dfp_read_field_def_feature(<<18, Rest/binary>>, Z1, Z2, + F@_1, F@_2, TrUserData) -> + d_field_feature_location(Rest, + Z1, + Z2, + F@_1, + F@_2, + TrUserData); +dfp_read_field_def_feature(<<>>, 0, 0, F@_1, F@_2, _) -> + S1 = #{name => F@_1}, + if F@_2 == '$undef' -> S1; + true -> S1#{location => F@_2} + end; +dfp_read_field_def_feature(Other, Z1, Z2, F@_1, F@_2, + TrUserData) -> + dg_read_field_def_feature(Other, + Z1, + Z2, + F@_1, + F@_2, + TrUserData). + +dg_read_field_def_feature(<<1:1, X:7, Rest/binary>>, N, + Acc, F@_1, F@_2, TrUserData) + when N < 32 - 7 -> + dg_read_field_def_feature(Rest, + N + 7, + X bsl N + Acc, + F@_1, + F@_2, + TrUserData); +dg_read_field_def_feature(<<0:1, X:7, Rest/binary>>, N, + Acc, F@_1, F@_2, TrUserData) -> + Key = X bsl N + Acc, + case Key of + 10 -> + d_field_feature_name(Rest, + 0, + 0, + F@_1, + F@_2, + TrUserData); + 18 -> + d_field_feature_location(Rest, + 0, + 0, + F@_1, + F@_2, + TrUserData); + _ -> + case Key band 7 of + 0 -> + skip_varint_feature(Rest, 0, 0, F@_1, F@_2, TrUserData); + 1 -> + skip_64_feature(Rest, 0, 0, F@_1, F@_2, TrUserData); + 2 -> + skip_length_delimited_feature(Rest, + 0, + 0, + F@_1, + F@_2, + TrUserData); + 3 -> + skip_group_feature(Rest, + Key bsr 3, + 0, + F@_1, + F@_2, + TrUserData); + 5 -> skip_32_feature(Rest, 0, 0, F@_1, F@_2, TrUserData) + end + end; +dg_read_field_def_feature(<<>>, 0, 0, F@_1, F@_2, _) -> + S1 = #{name => F@_1}, + if F@_2 == '$undef' -> S1; + true -> S1#{location => F@_2} + end. + +d_field_feature_name(<<1:1, X:7, Rest/binary>>, N, Acc, + F@_1, F@_2, TrUserData) + when N < 57 -> + d_field_feature_name(Rest, + N + 7, + X bsl N + Acc, + F@_1, + F@_2, + TrUserData); +d_field_feature_name(<<0:1, X:7, Rest/binary>>, N, Acc, + _, F@_2, TrUserData) -> + {NewFValue, RestF} = begin + Len = X bsl N + Acc, + <> = Rest, + {id(binary:copy(Bytes), TrUserData), Rest2} + end, + dfp_read_field_def_feature(RestF, + 0, + 0, + NewFValue, + F@_2, + TrUserData). + +d_field_feature_location(<<1:1, X:7, Rest/binary>>, N, + Acc, F@_1, F@_2, TrUserData) + when N < 57 -> + d_field_feature_location(Rest, + N + 7, + X bsl N + Acc, + F@_1, + F@_2, + TrUserData); +d_field_feature_location(<<0:1, X:7, Rest/binary>>, N, + Acc, F@_1, Prev, TrUserData) -> + {NewFValue, RestF} = begin + Len = X bsl N + Acc, + <> = Rest, + {id(decode_msg_point(Bs, TrUserData), TrUserData), + Rest2} + end, + dfp_read_field_def_feature(RestF, + 0, + 0, + F@_1, + if Prev == '$undef' -> NewFValue; + true -> + merge_msg_point(Prev, + NewFValue, + TrUserData) + end, + TrUserData). + +skip_varint_feature(<<1:1, _:7, Rest/binary>>, Z1, Z2, + F@_1, F@_2, TrUserData) -> + skip_varint_feature(Rest, + Z1, + Z2, + F@_1, + F@_2, + TrUserData); +skip_varint_feature(<<0:1, _:7, Rest/binary>>, Z1, Z2, + F@_1, F@_2, TrUserData) -> + dfp_read_field_def_feature(Rest, + Z1, + Z2, + F@_1, + F@_2, + TrUserData). + +skip_length_delimited_feature(<<1:1, X:7, Rest/binary>>, + N, Acc, F@_1, F@_2, TrUserData) + when N < 57 -> + skip_length_delimited_feature(Rest, + N + 7, + X bsl N + Acc, + F@_1, + F@_2, + TrUserData); +skip_length_delimited_feature(<<0:1, X:7, Rest/binary>>, + N, Acc, F@_1, F@_2, TrUserData) -> + Length = X bsl N + Acc, + <<_:Length/binary, Rest2/binary>> = Rest, + dfp_read_field_def_feature(Rest2, + 0, + 0, + F@_1, + F@_2, + TrUserData). + +skip_group_feature(Bin, FNum, Z2, F@_1, F@_2, + TrUserData) -> + {_, Rest} = read_group(Bin, FNum), + dfp_read_field_def_feature(Rest, + 0, + Z2, + F@_1, + F@_2, + TrUserData). + +skip_32_feature(<<_:32, Rest/binary>>, Z1, Z2, F@_1, + F@_2, TrUserData) -> + dfp_read_field_def_feature(Rest, + Z1, + Z2, + F@_1, + F@_2, + TrUserData). + +skip_64_feature(<<_:64, Rest/binary>>, Z1, Z2, F@_1, + F@_2, TrUserData) -> + dfp_read_field_def_feature(Rest, + Z1, + Z2, + F@_1, + F@_2, + TrUserData). + +decode_msg_route_note(Bin, TrUserData) -> + dfp_read_field_def_route_note(Bin, + 0, + 0, + id('$undef', TrUserData), + id(<<>>, TrUserData), + TrUserData). + +dfp_read_field_def_route_note(<<10, Rest/binary>>, Z1, + Z2, F@_1, F@_2, TrUserData) -> + d_field_route_note_location(Rest, + Z1, + Z2, + F@_1, + F@_2, + TrUserData); +dfp_read_field_def_route_note(<<18, Rest/binary>>, Z1, + Z2, F@_1, F@_2, TrUserData) -> + d_field_route_note_message(Rest, + Z1, + Z2, + F@_1, + F@_2, + TrUserData); +dfp_read_field_def_route_note(<<>>, 0, 0, F@_1, F@_2, + _) -> + S1 = #{message => F@_2}, + if F@_1 == '$undef' -> S1; + true -> S1#{location => F@_1} + end; +dfp_read_field_def_route_note(Other, Z1, Z2, F@_1, F@_2, + TrUserData) -> + dg_read_field_def_route_note(Other, + Z1, + Z2, + F@_1, + F@_2, + TrUserData). + +dg_read_field_def_route_note(<<1:1, X:7, Rest/binary>>, + N, Acc, F@_1, F@_2, TrUserData) + when N < 32 - 7 -> + dg_read_field_def_route_note(Rest, + N + 7, + X bsl N + Acc, + F@_1, + F@_2, + TrUserData); +dg_read_field_def_route_note(<<0:1, X:7, Rest/binary>>, + N, Acc, F@_1, F@_2, TrUserData) -> + Key = X bsl N + Acc, + case Key of + 10 -> + d_field_route_note_location(Rest, + 0, + 0, + F@_1, + F@_2, + TrUserData); + 18 -> + d_field_route_note_message(Rest, + 0, + 0, + F@_1, + F@_2, + TrUserData); + _ -> + case Key band 7 of + 0 -> + skip_varint_route_note(Rest, + 0, + 0, + F@_1, + F@_2, + TrUserData); + 1 -> + skip_64_route_note(Rest, 0, 0, F@_1, F@_2, TrUserData); + 2 -> + skip_length_delimited_route_note(Rest, + 0, + 0, + F@_1, + F@_2, + TrUserData); + 3 -> + skip_group_route_note(Rest, + Key bsr 3, + 0, + F@_1, + F@_2, + TrUserData); + 5 -> + skip_32_route_note(Rest, 0, 0, F@_1, F@_2, TrUserData) + end + end; +dg_read_field_def_route_note(<<>>, 0, 0, F@_1, F@_2, + _) -> + S1 = #{message => F@_2}, + if F@_1 == '$undef' -> S1; + true -> S1#{location => F@_1} + end. + +d_field_route_note_location(<<1:1, X:7, Rest/binary>>, + N, Acc, F@_1, F@_2, TrUserData) + when N < 57 -> + d_field_route_note_location(Rest, + N + 7, + X bsl N + Acc, + F@_1, + F@_2, + TrUserData); +d_field_route_note_location(<<0:1, X:7, Rest/binary>>, + N, Acc, Prev, F@_2, TrUserData) -> + {NewFValue, RestF} = begin + Len = X bsl N + Acc, + <> = Rest, + {id(decode_msg_point(Bs, TrUserData), TrUserData), + Rest2} + end, + dfp_read_field_def_route_note(RestF, + 0, + 0, + if Prev == '$undef' -> NewFValue; + true -> + merge_msg_point(Prev, + NewFValue, + TrUserData) + end, + F@_2, + TrUserData). + +d_field_route_note_message(<<1:1, X:7, Rest/binary>>, N, + Acc, F@_1, F@_2, TrUserData) + when N < 57 -> + d_field_route_note_message(Rest, + N + 7, + X bsl N + Acc, + F@_1, + F@_2, + TrUserData); +d_field_route_note_message(<<0:1, X:7, Rest/binary>>, N, + Acc, F@_1, _, TrUserData) -> + {NewFValue, RestF} = begin + Len = X bsl N + Acc, + <> = Rest, + {id(binary:copy(Bytes), TrUserData), Rest2} + end, + dfp_read_field_def_route_note(RestF, + 0, + 0, + F@_1, + NewFValue, + TrUserData). + +skip_varint_route_note(<<1:1, _:7, Rest/binary>>, Z1, + Z2, F@_1, F@_2, TrUserData) -> + skip_varint_route_note(Rest, + Z1, + Z2, + F@_1, + F@_2, + TrUserData); +skip_varint_route_note(<<0:1, _:7, Rest/binary>>, Z1, + Z2, F@_1, F@_2, TrUserData) -> + dfp_read_field_def_route_note(Rest, + Z1, + Z2, + F@_1, + F@_2, + TrUserData). + +skip_length_delimited_route_note(<<1:1, X:7, + Rest/binary>>, + N, Acc, F@_1, F@_2, TrUserData) + when N < 57 -> + skip_length_delimited_route_note(Rest, + N + 7, + X bsl N + Acc, + F@_1, + F@_2, + TrUserData); +skip_length_delimited_route_note(<<0:1, X:7, + Rest/binary>>, + N, Acc, F@_1, F@_2, TrUserData) -> + Length = X bsl N + Acc, + <<_:Length/binary, Rest2/binary>> = Rest, + dfp_read_field_def_route_note(Rest2, + 0, + 0, + F@_1, + F@_2, + TrUserData). + +skip_group_route_note(Bin, FNum, Z2, F@_1, F@_2, + TrUserData) -> + {_, Rest} = read_group(Bin, FNum), + dfp_read_field_def_route_note(Rest, + 0, + Z2, + F@_1, + F@_2, + TrUserData). + +skip_32_route_note(<<_:32, Rest/binary>>, Z1, Z2, F@_1, + F@_2, TrUserData) -> + dfp_read_field_def_route_note(Rest, + Z1, + Z2, + F@_1, + F@_2, + TrUserData). + +skip_64_route_note(<<_:64, Rest/binary>>, Z1, Z2, F@_1, + F@_2, TrUserData) -> + dfp_read_field_def_route_note(Rest, + Z1, + Z2, + F@_1, + F@_2, + TrUserData). + +decode_msg_route_summary(Bin, TrUserData) -> + dfp_read_field_def_route_summary(Bin, + 0, + 0, + id(0, TrUserData), + id(0, TrUserData), + id(0, TrUserData), + id(0, TrUserData), + TrUserData). + +dfp_read_field_def_route_summary(<<8, Rest/binary>>, Z1, + Z2, F@_1, F@_2, F@_3, F@_4, TrUserData) -> + d_field_route_summary_point_count(Rest, + Z1, + Z2, + F@_1, + F@_2, + F@_3, + F@_4, + TrUserData); +dfp_read_field_def_route_summary(<<16, Rest/binary>>, + Z1, Z2, F@_1, F@_2, F@_3, F@_4, TrUserData) -> + d_field_route_summary_feature_count(Rest, + Z1, + Z2, + F@_1, + F@_2, + F@_3, + F@_4, + TrUserData); +dfp_read_field_def_route_summary(<<24, Rest/binary>>, + Z1, Z2, F@_1, F@_2, F@_3, F@_4, TrUserData) -> + d_field_route_summary_distance(Rest, + Z1, + Z2, + F@_1, + F@_2, + F@_3, + F@_4, + TrUserData); +dfp_read_field_def_route_summary(<<32, Rest/binary>>, + Z1, Z2, F@_1, F@_2, F@_3, F@_4, TrUserData) -> + d_field_route_summary_elapsed_time(Rest, + Z1, + Z2, + F@_1, + F@_2, + F@_3, + F@_4, + TrUserData); +dfp_read_field_def_route_summary(<<>>, 0, 0, F@_1, F@_2, + F@_3, F@_4, _) -> + #{point_count => F@_1, feature_count => F@_2, + distance => F@_3, elapsed_time => F@_4}; +dfp_read_field_def_route_summary(Other, Z1, Z2, F@_1, + F@_2, F@_3, F@_4, TrUserData) -> + dg_read_field_def_route_summary(Other, + Z1, + Z2, + F@_1, + F@_2, + F@_3, + F@_4, + TrUserData). + +dg_read_field_def_route_summary(<<1:1, X:7, + Rest/binary>>, + N, Acc, F@_1, F@_2, F@_3, F@_4, TrUserData) + when N < 32 - 7 -> + dg_read_field_def_route_summary(Rest, + N + 7, + X bsl N + Acc, + F@_1, + F@_2, + F@_3, + F@_4, + TrUserData); +dg_read_field_def_route_summary(<<0:1, X:7, + Rest/binary>>, + N, Acc, F@_1, F@_2, F@_3, F@_4, TrUserData) -> + Key = X bsl N + Acc, + case Key of + 8 -> + d_field_route_summary_point_count(Rest, + 0, + 0, + F@_1, + F@_2, + F@_3, + F@_4, + TrUserData); + 16 -> + d_field_route_summary_feature_count(Rest, + 0, + 0, + F@_1, + F@_2, + F@_3, + F@_4, + TrUserData); + 24 -> + d_field_route_summary_distance(Rest, + 0, + 0, + F@_1, + F@_2, + F@_3, + F@_4, + TrUserData); + 32 -> + d_field_route_summary_elapsed_time(Rest, + 0, + 0, + F@_1, + F@_2, + F@_3, + F@_4, + TrUserData); + _ -> + case Key band 7 of + 0 -> + skip_varint_route_summary(Rest, + 0, + 0, + F@_1, + F@_2, + F@_3, + F@_4, + TrUserData); + 1 -> + skip_64_route_summary(Rest, + 0, + 0, + F@_1, + F@_2, + F@_3, + F@_4, + TrUserData); + 2 -> + skip_length_delimited_route_summary(Rest, + 0, + 0, + F@_1, + F@_2, + F@_3, + F@_4, + TrUserData); + 3 -> + skip_group_route_summary(Rest, + Key bsr 3, + 0, + F@_1, + F@_2, + F@_3, + F@_4, + TrUserData); + 5 -> + skip_32_route_summary(Rest, + 0, + 0, + F@_1, + F@_2, + F@_3, + F@_4, + TrUserData) + end + end; +dg_read_field_def_route_summary(<<>>, 0, 0, F@_1, F@_2, + F@_3, F@_4, _) -> + #{point_count => F@_1, feature_count => F@_2, + distance => F@_3, elapsed_time => F@_4}. + +d_field_route_summary_point_count(<<1:1, X:7, + Rest/binary>>, + N, Acc, F@_1, F@_2, F@_3, F@_4, TrUserData) + when N < 57 -> + d_field_route_summary_point_count(Rest, + N + 7, + X bsl N + Acc, + F@_1, + F@_2, + F@_3, + F@_4, + TrUserData); +d_field_route_summary_point_count(<<0:1, X:7, + Rest/binary>>, + N, Acc, _, F@_2, F@_3, F@_4, TrUserData) -> + {NewFValue, RestF} = {begin + <> = <<(X bsl N + + Acc):32/unsigned-native>>, + id(Res, TrUserData) + end, + Rest}, + dfp_read_field_def_route_summary(RestF, + 0, + 0, + NewFValue, + F@_2, + F@_3, + F@_4, + TrUserData). + +d_field_route_summary_feature_count(<<1:1, X:7, + Rest/binary>>, + N, Acc, F@_1, F@_2, F@_3, F@_4, TrUserData) + when N < 57 -> + d_field_route_summary_feature_count(Rest, + N + 7, + X bsl N + Acc, + F@_1, + F@_2, + F@_3, + F@_4, + TrUserData); +d_field_route_summary_feature_count(<<0:1, X:7, + Rest/binary>>, + N, Acc, F@_1, _, F@_3, F@_4, TrUserData) -> + {NewFValue, RestF} = {begin + <> = <<(X bsl N + + Acc):32/unsigned-native>>, + id(Res, TrUserData) + end, + Rest}, + dfp_read_field_def_route_summary(RestF, + 0, + 0, + F@_1, + NewFValue, + F@_3, + F@_4, + TrUserData). + +d_field_route_summary_distance(<<1:1, X:7, + Rest/binary>>, + N, Acc, F@_1, F@_2, F@_3, F@_4, TrUserData) + when N < 57 -> + d_field_route_summary_distance(Rest, + N + 7, + X bsl N + Acc, + F@_1, + F@_2, + F@_3, + F@_4, + TrUserData); +d_field_route_summary_distance(<<0:1, X:7, + Rest/binary>>, + N, Acc, F@_1, F@_2, _, F@_4, TrUserData) -> + {NewFValue, RestF} = {begin + <> = <<(X bsl N + + Acc):32/unsigned-native>>, + id(Res, TrUserData) + end, + Rest}, + dfp_read_field_def_route_summary(RestF, + 0, + 0, + F@_1, + F@_2, + NewFValue, + F@_4, + TrUserData). + +d_field_route_summary_elapsed_time(<<1:1, X:7, + Rest/binary>>, + N, Acc, F@_1, F@_2, F@_3, F@_4, TrUserData) + when N < 57 -> + d_field_route_summary_elapsed_time(Rest, + N + 7, + X bsl N + Acc, + F@_1, + F@_2, + F@_3, + F@_4, + TrUserData); +d_field_route_summary_elapsed_time(<<0:1, X:7, + Rest/binary>>, + N, Acc, F@_1, F@_2, F@_3, _, TrUserData) -> + {NewFValue, RestF} = {begin + <> = <<(X bsl N + + Acc):32/unsigned-native>>, + id(Res, TrUserData) + end, + Rest}, + dfp_read_field_def_route_summary(RestF, + 0, + 0, + F@_1, + F@_2, + F@_3, + NewFValue, + TrUserData). + +skip_varint_route_summary(<<1:1, _:7, Rest/binary>>, Z1, + Z2, F@_1, F@_2, F@_3, F@_4, TrUserData) -> + skip_varint_route_summary(Rest, + Z1, + Z2, + F@_1, + F@_2, + F@_3, + F@_4, + TrUserData); +skip_varint_route_summary(<<0:1, _:7, Rest/binary>>, Z1, + Z2, F@_1, F@_2, F@_3, F@_4, TrUserData) -> + dfp_read_field_def_route_summary(Rest, + Z1, + Z2, + F@_1, + F@_2, + F@_3, + F@_4, + TrUserData). + +skip_length_delimited_route_summary(<<1:1, X:7, + Rest/binary>>, + N, Acc, F@_1, F@_2, F@_3, F@_4, TrUserData) + when N < 57 -> + skip_length_delimited_route_summary(Rest, + N + 7, + X bsl N + Acc, + F@_1, + F@_2, + F@_3, + F@_4, + TrUserData); +skip_length_delimited_route_summary(<<0:1, X:7, + Rest/binary>>, + N, Acc, F@_1, F@_2, F@_3, F@_4, + TrUserData) -> + Length = X bsl N + Acc, + <<_:Length/binary, Rest2/binary>> = Rest, + dfp_read_field_def_route_summary(Rest2, + 0, + 0, + F@_1, + F@_2, + F@_3, + F@_4, + TrUserData). + +skip_group_route_summary(Bin, FNum, Z2, F@_1, F@_2, + F@_3, F@_4, TrUserData) -> + {_, Rest} = read_group(Bin, FNum), + dfp_read_field_def_route_summary(Rest, + 0, + Z2, + F@_1, + F@_2, + F@_3, + F@_4, + TrUserData). + +skip_32_route_summary(<<_:32, Rest/binary>>, Z1, Z2, + F@_1, F@_2, F@_3, F@_4, TrUserData) -> + dfp_read_field_def_route_summary(Rest, + Z1, + Z2, + F@_1, + F@_2, + F@_3, + F@_4, + TrUserData). + +skip_64_route_summary(<<_:64, Rest/binary>>, Z1, Z2, + F@_1, F@_2, F@_3, F@_4, TrUserData) -> + dfp_read_field_def_route_summary(Rest, + Z1, + Z2, + F@_1, + F@_2, + F@_3, + F@_4, + TrUserData). + +read_group(Bin, FieldNum) -> + {NumBytes, EndTagLen} = read_gr_b(Bin, 0, 0, 0, 0, FieldNum), + <> = Bin, + {Group, Rest}. + +%% Like skipping over fields, but record the total length, +%% Each field is <(FieldNum bsl 3) bor FieldType> ++ +%% Record the length because varints may be non-optimally encoded. +%% +%% Groups can be nested, but assume the same FieldNum cannot be nested +%% because group field numbers are shared with the rest of the fields +%% numbers. Thus we can search just for an group-end with the same +%% field number. +%% +%% (The only time the same group field number could occur would +%% be in a nested sub message, but then it would be inside a +%% length-delimited entry, which we skip-read by length.) +read_gr_b(<<1:1, X:7, Tl/binary>>, N, Acc, NumBytes, TagLen, FieldNum) + when N < (32-7) -> + read_gr_b(Tl, N+7, X bsl N + Acc, NumBytes, TagLen+1, FieldNum); +read_gr_b(<<0:1, X:7, Tl/binary>>, N, Acc, NumBytes, TagLen, + FieldNum) -> + Key = X bsl N + Acc, + TagLen1 = TagLen + 1, + case {Key bsr 3, Key band 7} of + {FieldNum, 4} -> % 4 = group_end + {NumBytes, TagLen1}; + {_, 0} -> % 0 = varint + read_gr_vi(Tl, 0, NumBytes + TagLen1, FieldNum); + {_, 1} -> % 1 = bits64 + <<_:64, Tl2/binary>> = Tl, + read_gr_b(Tl2, 0, 0, NumBytes + TagLen1 + 8, 0, FieldNum); + {_, 2} -> % 2 = length_delimited + read_gr_ld(Tl, 0, 0, NumBytes + TagLen1, FieldNum); + {_, 3} -> % 3 = group_start + read_gr_b(Tl, 0, 0, NumBytes + TagLen1, 0, FieldNum); + {_, 4} -> % 4 = group_end + read_gr_b(Tl, 0, 0, NumBytes + TagLen1, 0, FieldNum); + {_, 5} -> % 5 = bits32 + <<_:32, Tl2/binary>> = Tl, + read_gr_b(Tl2, 0, 0, NumBytes + TagLen1 + 4, 0, FieldNum) + end. + +read_gr_vi(<<1:1, _:7, Tl/binary>>, N, NumBytes, FieldNum) + when N < (64-7) -> + read_gr_vi(Tl, N+7, NumBytes+1, FieldNum); +read_gr_vi(<<0:1, _:7, Tl/binary>>, _, NumBytes, FieldNum) -> + read_gr_b(Tl, 0, 0, NumBytes+1, 0, FieldNum). + +read_gr_ld(<<1:1, X:7, Tl/binary>>, N, Acc, NumBytes, FieldNum) + when N < (64-7) -> + read_gr_ld(Tl, N+7, X bsl N + Acc, NumBytes+1, FieldNum); +read_gr_ld(<<0:1, X:7, Tl/binary>>, N, Acc, NumBytes, FieldNum) -> + Len = X bsl N + Acc, + NumBytes1 = NumBytes + 1, + <<_:Len/binary, Tl2/binary>> = Tl, + read_gr_b(Tl2, 0, 0, NumBytes1 + Len, 0, FieldNum). + +merge_msgs(Prev, New, MsgName) when is_atom(MsgName) -> + merge_msgs(Prev, New, MsgName, []). + +merge_msgs(Prev, New, MsgName, Opts) -> + TrUserData = proplists:get_value(user_data, Opts), + case MsgName of + empty -> merge_msg_empty(Prev, New, TrUserData); + point -> merge_msg_point(Prev, New, TrUserData); + rectangle -> merge_msg_rectangle(Prev, New, TrUserData); + feature -> merge_msg_feature(Prev, New, TrUserData); + route_note -> + merge_msg_route_note(Prev, New, TrUserData); + route_summary -> + merge_msg_route_summary(Prev, New, TrUserData) + end. + +-compile({nowarn_unused_function,merge_msg_empty/3}). +merge_msg_empty(_Prev, New, _TrUserData) -> New. + +-compile({nowarn_unused_function,merge_msg_point/3}). +merge_msg_point(PMsg, NMsg, _) -> + S1 = #{}, + S2 = case {PMsg, NMsg} of + {_, #{latitude := NFlatitude}} -> + S1#{latitude => NFlatitude}; + {#{latitude := PFlatitude}, _} -> + S1#{latitude => PFlatitude}; + _ -> S1 + end, + case {PMsg, NMsg} of + {_, #{longitude := NFlongitude}} -> + S2#{longitude => NFlongitude}; + {#{longitude := PFlongitude}, _} -> + S2#{longitude => PFlongitude}; + _ -> S2 + end. + +-compile({nowarn_unused_function,merge_msg_rectangle/3}). +merge_msg_rectangle(PMsg, NMsg, TrUserData) -> + S1 = #{}, + S2 = case {PMsg, NMsg} of + {#{lo := PFlo}, #{lo := NFlo}} -> + S1#{lo => merge_msg_point(PFlo, NFlo, TrUserData)}; + {_, #{lo := NFlo}} -> S1#{lo => NFlo}; + {#{lo := PFlo}, _} -> S1#{lo => PFlo}; + {_, _} -> S1 + end, + case {PMsg, NMsg} of + {#{hi := PFhi}, #{hi := NFhi}} -> + S2#{hi => merge_msg_point(PFhi, NFhi, TrUserData)}; + {_, #{hi := NFhi}} -> S2#{hi => NFhi}; + {#{hi := PFhi}, _} -> S2#{hi => PFhi}; + {_, _} -> S2 + end. + +-compile({nowarn_unused_function,merge_msg_feature/3}). +merge_msg_feature(PMsg, NMsg, TrUserData) -> + S1 = #{}, + S2 = case {PMsg, NMsg} of + {_, #{name := NFname}} -> S1#{name => NFname}; + {#{name := PFname}, _} -> S1#{name => PFname}; + _ -> S1 + end, + case {PMsg, NMsg} of + {#{location := PFlocation}, + #{location := NFlocation}} -> + S2#{location => + merge_msg_point(PFlocation, NFlocation, TrUserData)}; + {_, #{location := NFlocation}} -> + S2#{location => NFlocation}; + {#{location := PFlocation}, _} -> + S2#{location => PFlocation}; + {_, _} -> S2 + end. + +-compile({nowarn_unused_function,merge_msg_route_note/3}). +merge_msg_route_note(PMsg, NMsg, TrUserData) -> + S1 = #{}, + S2 = case {PMsg, NMsg} of + {#{location := PFlocation}, + #{location := NFlocation}} -> + S1#{location => + merge_msg_point(PFlocation, NFlocation, TrUserData)}; + {_, #{location := NFlocation}} -> + S1#{location => NFlocation}; + {#{location := PFlocation}, _} -> + S1#{location => PFlocation}; + {_, _} -> S1 + end, + case {PMsg, NMsg} of + {_, #{message := NFmessage}} -> + S2#{message => NFmessage}; + {#{message := PFmessage}, _} -> + S2#{message => PFmessage}; + _ -> S2 + end. + +-compile({nowarn_unused_function,merge_msg_route_summary/3}). +merge_msg_route_summary(PMsg, NMsg, _) -> + S1 = #{}, + S2 = case {PMsg, NMsg} of + {_, #{point_count := NFpoint_count}} -> + S1#{point_count => NFpoint_count}; + {#{point_count := PFpoint_count}, _} -> + S1#{point_count => PFpoint_count}; + _ -> S1 + end, + S3 = case {PMsg, NMsg} of + {_, #{feature_count := NFfeature_count}} -> + S2#{feature_count => NFfeature_count}; + {#{feature_count := PFfeature_count}, _} -> + S2#{feature_count => PFfeature_count}; + _ -> S2 + end, + S4 = case {PMsg, NMsg} of + {_, #{distance := NFdistance}} -> + S3#{distance => NFdistance}; + {#{distance := PFdistance}, _} -> + S3#{distance => PFdistance}; + _ -> S3 + end, + case {PMsg, NMsg} of + {_, #{elapsed_time := NFelapsed_time}} -> + S4#{elapsed_time => NFelapsed_time}; + {#{elapsed_time := PFelapsed_time}, _} -> + S4#{elapsed_time => PFelapsed_time}; + _ -> S4 + end. + + +verify_msg(Msg, MsgName) when is_atom(MsgName) -> + verify_msg(Msg, MsgName, []). + +verify_msg(Msg, MsgName, Opts) -> + TrUserData = proplists:get_value(user_data, Opts), + case MsgName of + empty -> v_msg_empty(Msg, [MsgName], TrUserData); + point -> v_msg_point(Msg, [MsgName], TrUserData); + rectangle -> + v_msg_rectangle(Msg, [MsgName], TrUserData); + feature -> v_msg_feature(Msg, [MsgName], TrUserData); + route_note -> + v_msg_route_note(Msg, [MsgName], TrUserData); + route_summary -> + v_msg_route_summary(Msg, [MsgName], TrUserData); + _ -> mk_type_error(not_a_known_message, Msg, []) + end. + + +-compile({nowarn_unused_function,v_msg_empty/3}). +-dialyzer({nowarn_function,v_msg_empty/3}). +v_msg_empty(#{} = M, Path, _) -> + lists:foreach(fun (OtherKey) -> + mk_type_error({extraneous_key, OtherKey}, M, Path) + end, + maps:keys(M)), + ok; +v_msg_empty(M, Path, _TrUserData) when is_map(M) -> + mk_type_error({missing_fields, + [] -- maps:keys(M), + empty}, + M, + Path); +v_msg_empty(X, Path, _TrUserData) -> + mk_type_error({expected_msg, empty}, X, Path). + +-compile({nowarn_unused_function,v_msg_point/3}). +-dialyzer({nowarn_function,v_msg_point/3}). +v_msg_point(#{} = M, Path, TrUserData) -> + case M of + #{latitude := F1} -> + v_type_int32(F1, [latitude | Path], TrUserData); + _ -> ok + end, + case M of + #{longitude := F2} -> + v_type_int32(F2, [longitude | Path], TrUserData); + _ -> ok + end, + lists:foreach(fun (latitude) -> ok; + (longitude) -> ok; + (OtherKey) -> + mk_type_error({extraneous_key, OtherKey}, M, Path) + end, + maps:keys(M)), + ok; +v_msg_point(M, Path, _TrUserData) when is_map(M) -> + mk_type_error({missing_fields, + [] -- maps:keys(M), + point}, + M, + Path); +v_msg_point(X, Path, _TrUserData) -> + mk_type_error({expected_msg, point}, X, Path). + +-compile({nowarn_unused_function,v_msg_rectangle/3}). +-dialyzer({nowarn_function,v_msg_rectangle/3}). +v_msg_rectangle(#{} = M, Path, TrUserData) -> + case M of + #{lo := F1} -> v_msg_point(F1, [lo | Path], TrUserData); + _ -> ok + end, + case M of + #{hi := F2} -> v_msg_point(F2, [hi | Path], TrUserData); + _ -> ok + end, + lists:foreach(fun (lo) -> ok; + (hi) -> ok; + (OtherKey) -> + mk_type_error({extraneous_key, OtherKey}, M, Path) + end, + maps:keys(M)), + ok; +v_msg_rectangle(M, Path, _TrUserData) when is_map(M) -> + mk_type_error({missing_fields, + [] -- maps:keys(M), + rectangle}, + M, + Path); +v_msg_rectangle(X, Path, _TrUserData) -> + mk_type_error({expected_msg, rectangle}, X, Path). + +-compile({nowarn_unused_function,v_msg_feature/3}). +-dialyzer({nowarn_function,v_msg_feature/3}). +v_msg_feature(#{} = M, Path, TrUserData) -> + case M of + #{name := F1} -> + v_type_string(F1, [name | Path], TrUserData); + _ -> ok + end, + case M of + #{location := F2} -> + v_msg_point(F2, [location | Path], TrUserData); + _ -> ok + end, + lists:foreach(fun (name) -> ok; + (location) -> ok; + (OtherKey) -> + mk_type_error({extraneous_key, OtherKey}, M, Path) + end, + maps:keys(M)), + ok; +v_msg_feature(M, Path, _TrUserData) when is_map(M) -> + mk_type_error({missing_fields, + [] -- maps:keys(M), + feature}, + M, + Path); +v_msg_feature(X, Path, _TrUserData) -> + mk_type_error({expected_msg, feature}, X, Path). + +-compile({nowarn_unused_function,v_msg_route_note/3}). +-dialyzer({nowarn_function,v_msg_route_note/3}). +v_msg_route_note(#{} = M, Path, TrUserData) -> + case M of + #{location := F1} -> + v_msg_point(F1, [location | Path], TrUserData); + _ -> ok + end, + case M of + #{message := F2} -> + v_type_string(F2, [message | Path], TrUserData); + _ -> ok + end, + lists:foreach(fun (location) -> ok; + (message) -> ok; + (OtherKey) -> + mk_type_error({extraneous_key, OtherKey}, M, Path) + end, + maps:keys(M)), + ok; +v_msg_route_note(M, Path, _TrUserData) when is_map(M) -> + mk_type_error({missing_fields, + [] -- maps:keys(M), + route_note}, + M, + Path); +v_msg_route_note(X, Path, _TrUserData) -> + mk_type_error({expected_msg, route_note}, X, Path). + +-compile({nowarn_unused_function,v_msg_route_summary/3}). +-dialyzer({nowarn_function,v_msg_route_summary/3}). +v_msg_route_summary(#{} = M, Path, TrUserData) -> + case M of + #{point_count := F1} -> + v_type_int32(F1, [point_count | Path], TrUserData); + _ -> ok + end, + case M of + #{feature_count := F2} -> + v_type_int32(F2, [feature_count | Path], TrUserData); + _ -> ok + end, + case M of + #{distance := F3} -> + v_type_int32(F3, [distance | Path], TrUserData); + _ -> ok + end, + case M of + #{elapsed_time := F4} -> + v_type_int32(F4, [elapsed_time | Path], TrUserData); + _ -> ok + end, + lists:foreach(fun (point_count) -> ok; + (feature_count) -> ok; + (distance) -> ok; + (elapsed_time) -> ok; + (OtherKey) -> + mk_type_error({extraneous_key, OtherKey}, M, Path) + end, + maps:keys(M)), + ok; +v_msg_route_summary(M, Path, _TrUserData) + when is_map(M) -> + mk_type_error({missing_fields, + [] -- maps:keys(M), + route_summary}, + M, + Path); +v_msg_route_summary(X, Path, _TrUserData) -> + mk_type_error({expected_msg, route_summary}, X, Path). + +-compile({nowarn_unused_function,v_type_int32/3}). +-dialyzer({nowarn_function,v_type_int32/3}). +v_type_int32(N, _Path, _TrUserData) + when -2147483648 =< N, N =< 2147483647 -> + ok; +v_type_int32(N, Path, _TrUserData) when is_integer(N) -> + mk_type_error({value_out_of_range, int32, signed, 32}, + N, + Path); +v_type_int32(X, Path, _TrUserData) -> + mk_type_error({bad_integer, int32, signed, 32}, + X, + Path). + +-compile({nowarn_unused_function,v_type_string/3}). +-dialyzer({nowarn_function,v_type_string/3}). +v_type_string(S, Path, _TrUserData) + when is_list(S); is_binary(S) -> + try unicode:characters_to_binary(S) of + B when is_binary(B) -> ok; + {error, _, _} -> + mk_type_error(bad_unicode_string, S, Path) + catch + error:badarg -> + mk_type_error(bad_unicode_string, S, Path) + end; +v_type_string(X, Path, _TrUserData) -> + mk_type_error(bad_unicode_string, X, Path). + +-compile({nowarn_unused_function,mk_type_error/3}). +-spec mk_type_error(_, _, list()) -> no_return(). +mk_type_error(Error, ValueSeen, Path) -> + Path2 = prettify_path(Path), + erlang:error({gpb_type_error, + {Error, [{value, ValueSeen}, {path, Path2}]}}). + + +-compile({nowarn_unused_function,prettify_path/1}). +-dialyzer({nowarn_function,prettify_path/1}). +prettify_path([]) -> top_level; +prettify_path(PathR) -> + list_to_atom(lists:append(lists:join(".", + lists:map(fun atom_to_list/1, + lists:reverse(PathR))))). + + +-compile({nowarn_unused_function,id/2}). +-compile({inline,id/2}). +id(X, _TrUserData) -> X. + +-compile({nowarn_unused_function,v_ok/3}). +-compile({inline,v_ok/3}). +v_ok(_Value, _Path, _TrUserData) -> ok. + +-compile({nowarn_unused_function,m_overwrite/3}). +-compile({inline,m_overwrite/3}). +m_overwrite(_Prev, New, _TrUserData) -> New. + +-compile({nowarn_unused_function,cons/3}). +-compile({inline,cons/3}). +cons(Elem, Acc, _TrUserData) -> [Elem | Acc]. + +-compile({nowarn_unused_function,lists_reverse/2}). +-compile({inline,lists_reverse/2}). +'lists_reverse'(L, _TrUserData) -> lists:reverse(L). +-compile({nowarn_unused_function,'erlang_++'/3}). +-compile({inline,'erlang_++'/3}). +'erlang_++'(A, B, _TrUserData) -> A ++ B. + +get_msg_defs() -> + [{{msg, empty}, []}, + {{msg, point}, + [#{name => latitude, fnum => 1, rnum => 2, + type => int32, occurrence => optional, opts => []}, + #{name => longitude, fnum => 2, rnum => 3, + type => int32, occurrence => optional, opts => []}]}, + {{msg, rectangle}, + [#{name => lo, fnum => 1, rnum => 2, + type => {msg, point}, occurrence => optional, + opts => []}, + #{name => hi, fnum => 2, rnum => 3, + type => {msg, point}, occurrence => optional, + opts => []}]}, + {{msg, feature}, + [#{name => name, fnum => 1, rnum => 2, type => string, + occurrence => optional, opts => []}, + #{name => location, fnum => 2, rnum => 3, + type => {msg, point}, occurrence => optional, + opts => []}]}, + {{msg, route_note}, + [#{name => location, fnum => 1, rnum => 2, + type => {msg, point}, occurrence => optional, + opts => []}, + #{name => message, fnum => 2, rnum => 3, type => string, + occurrence => optional, opts => []}]}, + {{msg, route_summary}, + [#{name => point_count, fnum => 1, rnum => 2, + type => int32, occurrence => optional, opts => []}, + #{name => feature_count, fnum => 2, rnum => 3, + type => int32, occurrence => optional, opts => []}, + #{name => distance, fnum => 3, rnum => 4, type => int32, + occurrence => optional, opts => []}, + #{name => elapsed_time, fnum => 4, rnum => 5, + type => int32, occurrence => optional, opts => []}]}]. + + +get_msg_names() -> + [empty, + point, + rectangle, + feature, + route_note, + route_summary]. + + +get_group_names() -> []. + + +get_msg_or_group_names() -> + [empty, + point, + rectangle, + feature, + route_note, + route_summary]. + + +get_enum_names() -> []. + + +fetch_msg_def(MsgName) -> + case find_msg_def(MsgName) of + Fs when is_list(Fs) -> Fs; + error -> erlang:error({no_such_msg, MsgName}) + end. + + +-spec fetch_enum_def(_) -> no_return(). +fetch_enum_def(EnumName) -> + erlang:error({no_such_enum, EnumName}). + + +find_msg_def(empty) -> []; +find_msg_def(point) -> + [#{name => latitude, fnum => 1, rnum => 2, + type => int32, occurrence => optional, opts => []}, + #{name => longitude, fnum => 2, rnum => 3, + type => int32, occurrence => optional, opts => []}]; +find_msg_def(rectangle) -> + [#{name => lo, fnum => 1, rnum => 2, + type => {msg, point}, occurrence => optional, + opts => []}, + #{name => hi, fnum => 2, rnum => 3, + type => {msg, point}, occurrence => optional, + opts => []}]; +find_msg_def(feature) -> + [#{name => name, fnum => 1, rnum => 2, type => string, + occurrence => optional, opts => []}, + #{name => location, fnum => 2, rnum => 3, + type => {msg, point}, occurrence => optional, + opts => []}]; +find_msg_def(route_note) -> + [#{name => location, fnum => 1, rnum => 2, + type => {msg, point}, occurrence => optional, + opts => []}, + #{name => message, fnum => 2, rnum => 3, type => string, + occurrence => optional, opts => []}]; +find_msg_def(route_summary) -> + [#{name => point_count, fnum => 1, rnum => 2, + type => int32, occurrence => optional, opts => []}, + #{name => feature_count, fnum => 2, rnum => 3, + type => int32, occurrence => optional, opts => []}, + #{name => distance, fnum => 3, rnum => 4, type => int32, + occurrence => optional, opts => []}, + #{name => elapsed_time, fnum => 4, rnum => 5, + type => int32, occurrence => optional, opts => []}]; +find_msg_def(_) -> error. + + +find_enum_def(_) -> error. + + +-spec enum_symbol_by_value(_, _) -> no_return(). +enum_symbol_by_value(E, V) -> + erlang:error({no_enum_defs, E, V}). + + +-spec enum_value_by_symbol(_, _) -> no_return(). +enum_value_by_symbol(E, V) -> + erlang:error({no_enum_defs, E, V}). + + + +get_service_names() -> ['routeguide.RouteGuide']. + + +get_service_def('routeguide.RouteGuide') -> + {{service, 'routeguide.RouteGuide'}, + [#{name => 'GetFeature', input => point, + output => feature, input_stream => false, + output_stream => false, opts => []}, + #{name => 'ListFeatures', input => rectangle, + output => feature, input_stream => false, + output_stream => true, opts => []}, + #{name => 'RecordRoute', input => point, + output => route_summary, input_stream => true, + output_stream => false, opts => []}, + #{name => 'RouteChat', input => route_note, + output => route_note, input_stream => true, + output_stream => true, opts => []}, + #{name => 'GenerateError', input => empty, + output => empty, input_stream => false, + output_stream => false, opts => []}, + #{name => 'StreamingGenerateError', input => empty, + output => empty, input_stream => false, + output_stream => true, opts => []}]}; +get_service_def(_) -> error. + + +get_rpc_names('routeguide.RouteGuide') -> + ['GetFeature', + 'ListFeatures', + 'RecordRoute', + 'RouteChat', + 'GenerateError', + 'StreamingGenerateError']; +get_rpc_names(_) -> error. + + +find_rpc_def('routeguide.RouteGuide', RpcName) -> + 'find_rpc_def_routeguide.RouteGuide'(RpcName); +find_rpc_def(_, _) -> error. + + +'find_rpc_def_routeguide.RouteGuide'('GetFeature') -> + #{name => 'GetFeature', input => point, + output => feature, input_stream => false, + output_stream => false, opts => []}; +'find_rpc_def_routeguide.RouteGuide'('ListFeatures') -> + #{name => 'ListFeatures', input => rectangle, + output => feature, input_stream => false, + output_stream => true, opts => []}; +'find_rpc_def_routeguide.RouteGuide'('RecordRoute') -> + #{name => 'RecordRoute', input => point, + output => route_summary, input_stream => true, + output_stream => false, opts => []}; +'find_rpc_def_routeguide.RouteGuide'('RouteChat') -> + #{name => 'RouteChat', input => route_note, + output => route_note, input_stream => true, + output_stream => true, opts => []}; +'find_rpc_def_routeguide.RouteGuide'('GenerateError') -> + #{name => 'GenerateError', input => empty, + output => empty, input_stream => false, + output_stream => false, opts => []}; +'find_rpc_def_routeguide.RouteGuide'('StreamingGenerateError') -> + #{name => 'StreamingGenerateError', input => empty, + output => empty, input_stream => false, + output_stream => true, opts => []}; +'find_rpc_def_routeguide.RouteGuide'(_) -> error. + + +fetch_rpc_def(ServiceName, RpcName) -> + case find_rpc_def(ServiceName, RpcName) of + Def when is_map(Def) -> Def; + error -> + erlang:error({no_such_rpc, ServiceName, RpcName}) + end. + + +%% Convert a a fully qualified (ie with package name) service name +%% as a binary to a service name as an atom. +fqbin_to_service_name(<<"routeguide.RouteGuide">>) -> + 'routeguide.RouteGuide'; +fqbin_to_service_name(X) -> + error({gpb_error, {badservice, X}}). + + +%% Convert a service name as an atom to a fully qualified +%% (ie with package name) name as a binary. +service_name_to_fqbin('routeguide.RouteGuide') -> + <<"routeguide.RouteGuide">>; +service_name_to_fqbin(X) -> + error({gpb_error, {badservice, X}}). + + +%% Convert a a fully qualified (ie with package name) service name +%% and an rpc name, both as binaries to a service name and an rpc +%% name, as atoms. +fqbins_to_service_and_rpc_name(<<"routeguide.RouteGuide">>, <<"GetFeature">>) -> + {'routeguide.RouteGuide', 'GetFeature'}; +fqbins_to_service_and_rpc_name(<<"routeguide.RouteGuide">>, <<"ListFeatures">>) -> + {'routeguide.RouteGuide', 'ListFeatures'}; +fqbins_to_service_and_rpc_name(<<"routeguide.RouteGuide">>, <<"RecordRoute">>) -> + {'routeguide.RouteGuide', 'RecordRoute'}; +fqbins_to_service_and_rpc_name(<<"routeguide.RouteGuide">>, <<"RouteChat">>) -> + {'routeguide.RouteGuide', 'RouteChat'}; +fqbins_to_service_and_rpc_name(<<"routeguide.RouteGuide">>, <<"GenerateError">>) -> + {'routeguide.RouteGuide', 'GenerateError'}; +fqbins_to_service_and_rpc_name(<<"routeguide.RouteGuide">>, <<"StreamingGenerateError">>) -> + {'routeguide.RouteGuide', 'StreamingGenerateError'}; +fqbins_to_service_and_rpc_name(S, R) -> + error({gpb_error, {badservice_or_rpc, {S, R}}}). + + +%% Convert a service name and an rpc name, both as atoms, +%% to a fully qualified (ie with package name) service name and +%% an rpc name as binaries. +service_and_rpc_name_to_fqbins('routeguide.RouteGuide', + 'GetFeature') -> + {<<"routeguide.RouteGuide">>, <<"GetFeature">>}; +service_and_rpc_name_to_fqbins('routeguide.RouteGuide', + 'ListFeatures') -> + {<<"routeguide.RouteGuide">>, <<"ListFeatures">>}; +service_and_rpc_name_to_fqbins('routeguide.RouteGuide', + 'RecordRoute') -> + {<<"routeguide.RouteGuide">>, <<"RecordRoute">>}; +service_and_rpc_name_to_fqbins('routeguide.RouteGuide', + 'RouteChat') -> + {<<"routeguide.RouteGuide">>, <<"RouteChat">>}; +service_and_rpc_name_to_fqbins('routeguide.RouteGuide', + 'GenerateError') -> + {<<"routeguide.RouteGuide">>, <<"GenerateError">>}; +service_and_rpc_name_to_fqbins('routeguide.RouteGuide', + 'StreamingGenerateError') -> + {<<"routeguide.RouteGuide">>, <<"StreamingGenerateError">>}; +service_and_rpc_name_to_fqbins(S, R) -> + error({gpb_error, {badservice_or_rpc, {S, R}}}). + + +fqbin_to_msg_name(<<"routeguide.Empty">>) -> empty; +fqbin_to_msg_name(<<"routeguide.Point">>) -> point; +fqbin_to_msg_name(<<"routeguide.Rectangle">>) -> rectangle; +fqbin_to_msg_name(<<"routeguide.Feature">>) -> feature; +fqbin_to_msg_name(<<"routeguide.RouteNote">>) -> route_note; +fqbin_to_msg_name(<<"routeguide.RouteSummary">>) -> route_summary; +fqbin_to_msg_name(E) -> error({gpb_error, {badmsg, E}}). + + +msg_name_to_fqbin(empty) -> <<"routeguide.Empty">>; +msg_name_to_fqbin(point) -> <<"routeguide.Point">>; +msg_name_to_fqbin(rectangle) -> <<"routeguide.Rectangle">>; +msg_name_to_fqbin(feature) -> <<"routeguide.Feature">>; +msg_name_to_fqbin(route_note) -> <<"routeguide.RouteNote">>; +msg_name_to_fqbin(route_summary) -> <<"routeguide.RouteSummary">>; +msg_name_to_fqbin(E) -> error({gpb_error, {badmsg, E}}). + + +-spec fqbin_to_enum_name(_) -> no_return(). +fqbin_to_enum_name(E) -> + error({gpb_error, {badenum, E}}). + + +-spec enum_name_to_fqbin(_) -> no_return(). +enum_name_to_fqbin(E) -> + error({gpb_error, {badenum, E}}). + + +get_package_name() -> routeguide. + + +%% Whether or not the message names +%% are prepended with package name or not. +uses_packages() -> true. + + +source_basename() -> "route_guide.proto". + + +%% Retrieve all proto file names, also imported ones. +%% The order is top-down. The first element is always the main +%% source file. The files are returned with extension, +%% see get_all_proto_names/0 for a version that returns +%% the basenames sans extension +get_all_source_basenames() -> ["route_guide.proto"]. + + +%% Retrieve all proto file names, also imported ones. +%% The order is top-down. The first element is always the main +%% source file. The files are returned sans .proto extension, +%% to make it easier to use them with the various get_xyz_containment +%% functions. +get_all_proto_names() -> ["route_guide"]. + + +get_msg_containment("route_guide") -> + [empty, + feature, + point, + rectangle, + route_note, + route_summary]; +get_msg_containment(P) -> + error({gpb_error, {badproto, P}}). + + +get_pkg_containment("route_guide") -> routeguide; +get_pkg_containment(P) -> + error({gpb_error, {badproto, P}}). + + +get_service_containment("route_guide") -> + ['routeguide.RouteGuide']; +get_service_containment(P) -> + error({gpb_error, {badproto, P}}). + + +get_rpc_containment("route_guide") -> + [{'routeguide.RouteGuide', 'GetFeature'}, + {'routeguide.RouteGuide', 'ListFeatures'}, + {'routeguide.RouteGuide', 'RecordRoute'}, + {'routeguide.RouteGuide', 'RouteChat'}, + {'routeguide.RouteGuide', 'GenerateError'}, + {'routeguide.RouteGuide', 'StreamingGenerateError'}]; +get_rpc_containment(P) -> + error({gpb_error, {badproto, P}}). + + +get_enum_containment("route_guide") -> []; +get_enum_containment(P) -> + error({gpb_error, {badproto, P}}). + + +get_proto_by_msg_name_as_fqbin(<<"routeguide.Point">>) -> + "route_guide"; +get_proto_by_msg_name_as_fqbin(<<"routeguide.RouteNote">>) -> + "route_guide"; +get_proto_by_msg_name_as_fqbin(<<"routeguide.Rectangle">>) -> + "route_guide"; +get_proto_by_msg_name_as_fqbin(<<"routeguide.Feature">>) -> + "route_guide"; +get_proto_by_msg_name_as_fqbin(<<"routeguide.RouteSummary">>) -> + "route_guide"; +get_proto_by_msg_name_as_fqbin(<<"routeguide.Empty">>) -> + "route_guide"; +get_proto_by_msg_name_as_fqbin(E) -> + error({gpb_error, {badmsg, E}}). + + +get_proto_by_service_name_as_fqbin(<<"routeguide.RouteGuide">>) -> + "route_guide"; +get_proto_by_service_name_as_fqbin(E) -> + error({gpb_error, {badservice, E}}). + + +-spec get_proto_by_enum_name_as_fqbin(_) -> no_return(). +get_proto_by_enum_name_as_fqbin(E) -> + error({gpb_error, {badenum, E}}). + + +get_protos_by_pkg_name_as_fqbin(<<"routeguide">>) -> + ["route_guide"]; +get_protos_by_pkg_name_as_fqbin(E) -> + error({gpb_error, {badpkg, E}}). + + +descriptor() -> + <<10, 160, 6, 10, 28, 114, 111, 117, 116, 101, 103, 117, + 105, 100, 101, 47, 114, 111, 117, 116, 101, 95, 103, + 117, 105, 100, 101, 46, 112, 114, 111, 116, 111, 18, 10, + 114, 111, 117, 116, 101, 103, 117, 105, 100, 101, 34, 7, + 10, 5, 69, 109, 112, 116, 121, 34, 60, 10, 7, 70, 101, + 97, 116, 117, 114, 101, 18, 12, 10, 4, 110, 97, 109, + 101, 24, 1, 32, 1, 40, 9, 18, 35, 10, 8, 108, 111, 99, + 97, 116, 105, 111, 110, 24, 2, 32, 1, 40, 11, 50, 17, + 46, 114, 111, 117, 116, 101, 103, 117, 105, 100, 101, + 46, 80, 111, 105, 110, 116, 34, 44, 10, 5, 80, 111, 105, + 110, 116, 18, 16, 10, 8, 108, 97, 116, 105, 116, 117, + 100, 101, 24, 1, 32, 1, 40, 5, 18, 17, 10, 9, 108, 111, + 110, 103, 105, 116, 117, 100, 101, 24, 2, 32, 1, 40, 5, + 34, 73, 10, 9, 82, 101, 99, 116, 97, 110, 103, 108, 101, + 18, 29, 10, 2, 108, 111, 24, 1, 32, 1, 40, 11, 50, 17, + 46, 114, 111, 117, 116, 101, 103, 117, 105, 100, 101, + 46, 80, 111, 105, 110, 116, 18, 29, 10, 2, 104, 105, 24, + 2, 32, 1, 40, 11, 50, 17, 46, 114, 111, 117, 116, 101, + 103, 117, 105, 100, 101, 46, 80, 111, 105, 110, 116, 34, + 65, 10, 9, 82, 111, 117, 116, 101, 78, 111, 116, 101, + 18, 35, 10, 8, 108, 111, 99, 97, 116, 105, 111, 110, 24, + 1, 32, 1, 40, 11, 50, 17, 46, 114, 111, 117, 116, 101, + 103, 117, 105, 100, 101, 46, 80, 111, 105, 110, 116, 18, + 15, 10, 7, 109, 101, 115, 115, 97, 103, 101, 24, 2, 32, + 1, 40, 9, 34, 98, 10, 12, 82, 111, 117, 116, 101, 83, + 117, 109, 109, 97, 114, 121, 18, 19, 10, 11, 112, 111, + 105, 110, 116, 95, 99, 111, 117, 110, 116, 24, 1, 32, 1, + 40, 5, 18, 21, 10, 13, 102, 101, 97, 116, 117, 114, 101, + 95, 99, 111, 117, 110, 116, 24, 2, 32, 1, 40, 5, 18, 16, + 10, 8, 100, 105, 115, 116, 97, 110, 99, 101, 24, 3, 32, + 1, 40, 5, 18, 20, 10, 12, 101, 108, 97, 112, 115, 101, + 100, 95, 116, 105, 109, 101, 24, 4, 32, 1, 40, 5, 50, + 132, 3, 10, 10, 82, 111, 117, 116, 101, 71, 117, 105, + 100, 101, 18, 56, 10, 10, 71, 101, 116, 70, 101, 97, + 116, 117, 114, 101, 18, 17, 46, 114, 111, 117, 116, 101, + 103, 117, 105, 100, 101, 46, 80, 111, 105, 110, 116, 26, + 19, 46, 114, 111, 117, 116, 101, 103, 117, 105, 100, + 101, 46, 70, 101, 97, 116, 117, 114, 101, 40, 0, 48, 0, + 18, 62, 10, 12, 76, 105, 115, 116, 70, 101, 97, 116, + 117, 114, 101, 115, 18, 21, 46, 114, 111, 117, 116, 101, + 103, 117, 105, 100, 101, 46, 82, 101, 99, 116, 97, 110, + 103, 108, 101, 26, 19, 46, 114, 111, 117, 116, 101, 103, + 117, 105, 100, 101, 46, 70, 101, 97, 116, 117, 114, 101, + 40, 0, 48, 0, 18, 62, 10, 11, 82, 101, 99, 111, 114, + 100, 82, 111, 117, 116, 101, 18, 17, 46, 114, 111, 117, + 116, 101, 103, 117, 105, 100, 101, 46, 80, 111, 105, + 110, 116, 26, 24, 46, 114, 111, 117, 116, 101, 103, 117, + 105, 100, 101, 46, 82, 111, 117, 116, 101, 83, 117, 109, + 109, 97, 114, 121, 40, 0, 48, 0, 18, 61, 10, 9, 82, 111, + 117, 116, 101, 67, 104, 97, 116, 18, 21, 46, 114, 111, + 117, 116, 101, 103, 117, 105, 100, 101, 46, 82, 111, + 117, 116, 101, 78, 111, 116, 101, 26, 21, 46, 114, 111, + 117, 116, 101, 103, 117, 105, 100, 101, 46, 82, 111, + 117, 116, 101, 78, 111, 116, 101, 40, 0, 48, 0, 18, 57, + 10, 13, 71, 101, 110, 101, 114, 97, 116, 101, 69, 114, + 114, 111, 114, 18, 17, 46, 114, 111, 117, 116, 101, 103, + 117, 105, 100, 101, 46, 69, 109, 112, 116, 121, 26, 17, + 46, 114, 111, 117, 116, 101, 103, 117, 105, 100, 101, + 46, 69, 109, 112, 116, 121, 40, 0, 48, 0, 18, 66, 10, + 22, 83, 116, 114, 101, 97, 109, 105, 110, 103, 71, 101, + 110, 101, 114, 97, 116, 101, 69, 114, 114, 111, 114, 18, + 17, 46, 114, 111, 117, 116, 101, 103, 117, 105, 100, + 101, 46, 69, 109, 112, 116, 121, 26, 17, 46, 114, 111, + 117, 116, 101, 103, 117, 105, 100, 101, 46, 69, 109, + 112, 116, 121, 40, 0, 48, 0, 98, 6, 112, 114, 111, 116, + 111, 51>>. + +descriptor("route_guide") -> + <<10, 28, 114, 111, 117, 116, 101, 103, 117, 105, 100, + 101, 47, 114, 111, 117, 116, 101, 95, 103, 117, 105, + 100, 101, 46, 112, 114, 111, 116, 111, 18, 10, 114, 111, + 117, 116, 101, 103, 117, 105, 100, 101, 34, 7, 10, 5, + 69, 109, 112, 116, 121, 34, 60, 10, 7, 70, 101, 97, 116, + 117, 114, 101, 18, 12, 10, 4, 110, 97, 109, 101, 24, 1, + 32, 1, 40, 9, 18, 35, 10, 8, 108, 111, 99, 97, 116, 105, + 111, 110, 24, 2, 32, 1, 40, 11, 50, 17, 46, 114, 111, + 117, 116, 101, 103, 117, 105, 100, 101, 46, 80, 111, + 105, 110, 116, 34, 44, 10, 5, 80, 111, 105, 110, 116, + 18, 16, 10, 8, 108, 97, 116, 105, 116, 117, 100, 101, + 24, 1, 32, 1, 40, 5, 18, 17, 10, 9, 108, 111, 110, 103, + 105, 116, 117, 100, 101, 24, 2, 32, 1, 40, 5, 34, 73, + 10, 9, 82, 101, 99, 116, 97, 110, 103, 108, 101, 18, 29, + 10, 2, 108, 111, 24, 1, 32, 1, 40, 11, 50, 17, 46, 114, + 111, 117, 116, 101, 103, 117, 105, 100, 101, 46, 80, + 111, 105, 110, 116, 18, 29, 10, 2, 104, 105, 24, 2, 32, + 1, 40, 11, 50, 17, 46, 114, 111, 117, 116, 101, 103, + 117, 105, 100, 101, 46, 80, 111, 105, 110, 116, 34, 65, + 10, 9, 82, 111, 117, 116, 101, 78, 111, 116, 101, 18, + 35, 10, 8, 108, 111, 99, 97, 116, 105, 111, 110, 24, 1, + 32, 1, 40, 11, 50, 17, 46, 114, 111, 117, 116, 101, 103, + 117, 105, 100, 101, 46, 80, 111, 105, 110, 116, 18, 15, + 10, 7, 109, 101, 115, 115, 97, 103, 101, 24, 2, 32, 1, + 40, 9, 34, 98, 10, 12, 82, 111, 117, 116, 101, 83, 117, + 109, 109, 97, 114, 121, 18, 19, 10, 11, 112, 111, 105, + 110, 116, 95, 99, 111, 117, 110, 116, 24, 1, 32, 1, 40, + 5, 18, 21, 10, 13, 102, 101, 97, 116, 117, 114, 101, 95, + 99, 111, 117, 110, 116, 24, 2, 32, 1, 40, 5, 18, 16, 10, + 8, 100, 105, 115, 116, 97, 110, 99, 101, 24, 3, 32, 1, + 40, 5, 18, 20, 10, 12, 101, 108, 97, 112, 115, 101, 100, + 95, 116, 105, 109, 101, 24, 4, 32, 1, 40, 5, 50, 132, 3, + 10, 10, 82, 111, 117, 116, 101, 71, 117, 105, 100, 101, + 18, 56, 10, 10, 71, 101, 116, 70, 101, 97, 116, 117, + 114, 101, 18, 17, 46, 114, 111, 117, 116, 101, 103, 117, + 105, 100, 101, 46, 80, 111, 105, 110, 116, 26, 19, 46, + 114, 111, 117, 116, 101, 103, 117, 105, 100, 101, 46, + 70, 101, 97, 116, 117, 114, 101, 40, 0, 48, 0, 18, 62, + 10, 12, 76, 105, 115, 116, 70, 101, 97, 116, 117, 114, + 101, 115, 18, 21, 46, 114, 111, 117, 116, 101, 103, 117, + 105, 100, 101, 46, 82, 101, 99, 116, 97, 110, 103, 108, + 101, 26, 19, 46, 114, 111, 117, 116, 101, 103, 117, 105, + 100, 101, 46, 70, 101, 97, 116, 117, 114, 101, 40, 0, + 48, 0, 18, 62, 10, 11, 82, 101, 99, 111, 114, 100, 82, + 111, 117, 116, 101, 18, 17, 46, 114, 111, 117, 116, 101, + 103, 117, 105, 100, 101, 46, 80, 111, 105, 110, 116, 26, + 24, 46, 114, 111, 117, 116, 101, 103, 117, 105, 100, + 101, 46, 82, 111, 117, 116, 101, 83, 117, 109, 109, 97, + 114, 121, 40, 0, 48, 0, 18, 61, 10, 9, 82, 111, 117, + 116, 101, 67, 104, 97, 116, 18, 21, 46, 114, 111, 117, + 116, 101, 103, 117, 105, 100, 101, 46, 82, 111, 117, + 116, 101, 78, 111, 116, 101, 26, 21, 46, 114, 111, 117, + 116, 101, 103, 117, 105, 100, 101, 46, 82, 111, 117, + 116, 101, 78, 111, 116, 101, 40, 0, 48, 0, 18, 57, 10, + 13, 71, 101, 110, 101, 114, 97, 116, 101, 69, 114, 114, + 111, 114, 18, 17, 46, 114, 111, 117, 116, 101, 103, 117, + 105, 100, 101, 46, 69, 109, 112, 116, 121, 26, 17, 46, + 114, 111, 117, 116, 101, 103, 117, 105, 100, 101, 46, + 69, 109, 112, 116, 121, 40, 0, 48, 0, 18, 66, 10, 22, + 83, 116, 114, 101, 97, 109, 105, 110, 103, 71, 101, 110, + 101, 114, 97, 116, 101, 69, 114, 114, 111, 114, 18, 17, + 46, 114, 111, 117, 116, 101, 103, 117, 105, 100, 101, + 46, 69, 109, 112, 116, 121, 26, 17, 46, 114, 111, 117, + 116, 101, 103, 117, 105, 100, 101, 46, 69, 109, 112, + 116, 121, 40, 0, 48, 0, 98, 6, 112, 114, 111, 116, 111, + 51>>; +descriptor(X) -> error({gpb_error, {badname, X}}). + + +gpb_version_as_string() -> + "4.7.3". + +gpb_version_as_list() -> + [4,7,3]. diff --git a/instrumentation/opentelemetry_grpcbox/test/routeguide_route_guide.erl b/instrumentation/opentelemetry_grpcbox/test/routeguide_route_guide.erl new file mode 100644 index 0000000..00ce166 --- /dev/null +++ b/instrumentation/opentelemetry_grpcbox/test/routeguide_route_guide.erl @@ -0,0 +1,129 @@ +-module(routeguide_route_guide). + +-include_lib("grpcbox/include/grpcbox.hrl"). + +-export([get_feature/2, + list_features/2, + record_route/2, + route_chat/2, + generate_error/2, + streaming_generate_error/2]). + +-type route_summary() :: + #{point_count => integer(), + feature_count => integer(), + distance => integer(), + elapsed_time => integer()}. + +-type point() :: + #{latitude => integer(), + longitude => integer()}. + +-type rectangle() :: + #{lo => point(), + hi => point()}. + +-type route_note() :: + #{location => point(), + message => string()}. + +-type feature() :: + #{name => string(), + location => point()}. + +-spec get_feature(Ctx :: ctx:ctx(), Message :: point()) -> {ok, feature(), ctx:ctx()}. +get_feature(Ctx, Message) -> + Feature = #{name => find_point(Message, data()), + location => Message}, + {ok, Feature, Ctx}. + +-spec list_features(Message::rectangle(), GrpcStream :: grpcbox_stream:t()) -> ok. +list_features(_Message, GrpcStream) -> + grpcbox_stream:add_headers([{<<"info">>, <<"this is a test-implementation">>}], GrpcStream), + grpcbox_stream:send(#{name => <<"Tour Eiffel">>, + location => #{latitude => 3, + longitude => 5}}, GrpcStream), + grpcbox_stream:send(#{name => <<"Louvre">>, + location => #{latitude => 4, + longitude => 5}}, GrpcStream), + + grpcbox_stream:add_trailers([{<<"nr_of_points_sent">>, <<"2">>}], GrpcStream), + ok. + +-spec record_route(reference(), GrpcStream :: grpcbox_stream:t()) -> {ok, route_summary(), grpcbox_stream:t()}. +record_route(Ref, GrpcStream) -> + record_route(Ref, #{t_start => erlang:system_time(1), + acc => []}, GrpcStream). + +record_route(Ref, Data=#{t_start := T0, acc := Points}, GrpcStream) -> + receive + {Ref, eos} -> + %% receiving 'eos' tells us that we need to return a result. + {ok, #{elapsed_time => erlang:system_time(1) - T0, + point_count => length(Points), + feature_count => count_features(Points), + distance => distance(Points)}, GrpcStream}; + {Ref, Point} -> + record_route(Ref, Data#{acc => [Point | Points]}, GrpcStream) + end. + +-spec route_chat(reference(), GrpcStream :: grpcbox_stream:t()) -> ok. +route_chat(Ref, GrpcStream) -> + route_chat(Ref, [], GrpcStream). + +route_chat(Ref, Data, GrpcStream) -> + receive + {Ref, eos} -> + ok; + {Ref, #{location := Location} = P} -> + Messages = proplists:get_all_values(Location, Data), + [grpcbox_stream:send(Message, GrpcStream) || Message <- Messages], + route_chat(Ref, [{Location, P} | Data], GrpcStream) + end. + +-spec generate_error(Ctx :: ctx:ctx(), Message :: map()) -> grpcbox_stream:grpc_extended_error_response(). +generate_error(_Ctx, _Message) -> + { + grpc_extended_error, #{ + status => ?GRPC_STATUS_INTERNAL, + message => <<"error_message">>, + trailers => #{ + <<"generate_error_trailer">> => <<"error_trailer">> + } + } + }. + +-spec streaming_generate_error(Message :: map(), GrpcStream :: grpcbox_stream:t()) -> no_return(). +streaming_generate_error(_Message, _GrpcStream) -> + exit( + { + grpc_extended_error, #{ + status => ?GRPC_STATUS_INTERNAL, + message => <<"error_message">>, + trailers => #{ + <<"generate_error_trailer">> => <<"error_trailer">> + } + } + } + ). + +%% Supporting functions + +data() -> + case file:read_file("test/otel_interceptor_SUITE_data/route_guide_db.json") of + {ok, Json} -> + jsx:decode(Json, [return_maps, {labels, atom}]); + {error, enoent} -> + {ok, Json} = file:read_file("../../../../test/otel_interceptor_SUITE_data/route_guide_db.json"), + jsx:decode(Json, [return_maps, {labels, atom}]) + end. + +find_point(_Location, []) -> + ""; +find_point(Location, [#{location := Location, name := Name} | _]) -> + Name; +find_point(Location, [_ | T]) -> + find_point(Location, T). + +count_features(_) -> 42. +distance(_) -> 42. diff --git a/instrumentation/opentelemetry_grpcbox/test/routeguide_route_guide_bhvr.erl b/instrumentation/opentelemetry_grpcbox/test/routeguide_route_guide_bhvr.erl new file mode 100644 index 0000000..524c873 --- /dev/null +++ b/instrumentation/opentelemetry_grpcbox/test/routeguide_route_guide_bhvr.erl @@ -0,0 +1,33 @@ +%%%------------------------------------------------------------------- +%% @doc Behaviour to implement for grpc service routeguide.RouteGuide. +%% @end +%%%------------------------------------------------------------------- + +%% this module was generated on 2022-03-16T12:32:26+00:00 and should not be modified manually + +-module(routeguide_route_guide_bhvr). + +%% @doc Unary RPC +-callback get_feature(ctx:ctx(), route_guide_pb:point()) -> + {ok, route_guide_pb:feature(), ctx:ctx()} | grpcbox_stream:grpc_error_response(). + +%% @doc +-callback list_features(route_guide_pb:rectangle(), grpcbox_stream:t()) -> + ok | grpcbox_stream:grpc_error_response(). + +%% @doc +-callback record_route(reference(), grpcbox_stream:t()) -> + {ok, route_guide_pb:route_summary(), ctx:ctx()} | grpcbox_stream:grpc_error_response(). + +%% @doc +-callback route_chat(reference(), grpcbox_stream:t()) -> + ok | grpcbox_stream:grpc_error_response(). + +%% @doc Unary RPC +-callback generate_error(ctx:ctx(), route_guide_pb:empty()) -> + {ok, route_guide_pb:empty(), ctx:ctx()} | grpcbox_stream:grpc_error_response(). + +%% @doc +-callback streaming_generate_error(route_guide_pb:empty(), grpcbox_stream:t()) -> + ok | grpcbox_stream:grpc_error_response(). + diff --git a/instrumentation/opentelemetry_grpcbox/test/routeguide_route_guide_client.erl b/instrumentation/opentelemetry_grpcbox/test/routeguide_route_guide_client.erl new file mode 100644 index 0000000..4771c7c --- /dev/null +++ b/instrumentation/opentelemetry_grpcbox/test/routeguide_route_guide_client.erl @@ -0,0 +1,133 @@ +%%%------------------------------------------------------------------- +%% @doc Client module for grpc service routeguide.RouteGuide. +%% @end +%%%------------------------------------------------------------------- + +%% this module was generated on 2022-03-16T12:32:26+00:00 and should not be modified manually + +-module(routeguide_route_guide_client). + +-compile(export_all). +-compile(nowarn_export_all). + +-include_lib("grpcbox/include/grpcbox.hrl"). + +-define(is_ctx(Ctx), is_tuple(Ctx) andalso element(1, Ctx) =:= ctx). + +-define(SERVICE, 'routeguide.RouteGuide'). +-define(PROTO_MODULE, 'route_guide_pb'). +-define(MARSHAL_FUN(T), fun(I) -> ?PROTO_MODULE:encode_msg(I, T) end). +-define(UNMARSHAL_FUN(T), fun(I) -> ?PROTO_MODULE:decode_msg(I, T) end). +-define(DEF(Input, Output, MessageType), #grpcbox_def{service=?SERVICE, + message_type=MessageType, + marshal_fun=?MARSHAL_FUN(Input), + unmarshal_fun=?UNMARSHAL_FUN(Output)}). + +%% @doc Unary RPC +-spec get_feature(route_guide_pb:point()) -> + {ok, route_guide_pb:feature(), grpcbox:metadata()} | grpcbox_stream:grpc_error_response(). +get_feature(Input) -> + get_feature(ctx:new(), Input, #{}). + +-spec get_feature(ctx:t() | route_guide_pb:point(), route_guide_pb:point() | grpcbox_client:options()) -> + {ok, route_guide_pb:feature(), grpcbox:metadata()} | grpcbox_stream:grpc_error_response(). +get_feature(Ctx, Input) when ?is_ctx(Ctx) -> + get_feature(Ctx, Input, #{}); +get_feature(Input, Options) -> + get_feature(ctx:new(), Input, Options). + +-spec get_feature(ctx:t(), route_guide_pb:point(), grpcbox_client:options()) -> + {ok, route_guide_pb:feature(), grpcbox:metadata()} | grpcbox_stream:grpc_error_response(). +get_feature(Ctx, Input, Options) -> + grpcbox_client:unary(Ctx, <<"/routeguide.RouteGuide/GetFeature">>, Input, ?DEF(point, feature, <<"routeguide.Point">>), Options). + +%% @doc +-spec list_features(route_guide_pb:rectangle()) -> + {ok, grpcbox_client:stream()} | grpcbox_stream:grpc_error_response(). +list_features(Input) -> + list_features(ctx:new(), Input, #{}). + +-spec list_features(ctx:t() | route_guide_pb:rectangle(), route_guide_pb:rectangle() | grpcbox_client:options()) -> + {ok, grpcbox_client:stream()} | grpcbox_stream:grpc_error_response(). +list_features(Ctx, Input) when ?is_ctx(Ctx) -> + list_features(Ctx, Input, #{}); +list_features(Input, Options) -> + list_features(ctx:new(), Input, Options). + +-spec list_features(ctx:t(), route_guide_pb:rectangle(), grpcbox_client:options()) -> + {ok, grpcbox_client:stream()} | grpcbox_stream:grpc_error_response(). +list_features(Ctx, Input, Options) -> + grpcbox_client:stream(Ctx, <<"/routeguide.RouteGuide/ListFeatures">>, Input, ?DEF(rectangle, feature, <<"routeguide.Rectangle">>), Options). + +%% @doc +-spec record_route() -> + {ok, grpcbox_client:stream()} | grpcbox_stream:grpc_error_response(). +record_route() -> + record_route(ctx:new(), #{}). + +-spec record_route(ctx:t() | grpcbox_client:options()) -> + {ok, grpcbox_client:stream()} | grpcbox_stream:grpc_error_response(). +record_route(Ctx) when ?is_ctx(Ctx) -> + record_route(Ctx, #{}); +record_route(Options) -> + record_route(ctx:new(), Options). + +-spec record_route(ctx:t(), grpcbox_client:options()) -> + {ok, grpcbox_client:stream()} | grpcbox_stream:grpc_error_response(). +record_route(Ctx, Options) -> + grpcbox_client:stream(Ctx, <<"/routeguide.RouteGuide/RecordRoute">>, ?DEF(point, route_summary, <<"routeguide.Point">>), Options). + +%% @doc +-spec route_chat() -> + {ok, grpcbox_client:stream()} | grpcbox_stream:grpc_error_response(). +route_chat() -> + route_chat(ctx:new(), #{}). + +-spec route_chat(ctx:t() | grpcbox_client:options()) -> + {ok, grpcbox_client:stream()} | grpcbox_stream:grpc_error_response(). +route_chat(Ctx) when ?is_ctx(Ctx) -> + route_chat(Ctx, #{}); +route_chat(Options) -> + route_chat(ctx:new(), Options). + +-spec route_chat(ctx:t(), grpcbox_client:options()) -> + {ok, grpcbox_client:stream()} | grpcbox_stream:grpc_error_response(). +route_chat(Ctx, Options) -> + grpcbox_client:stream(Ctx, <<"/routeguide.RouteGuide/RouteChat">>, ?DEF(route_note, route_note, <<"routeguide.RouteNote">>), Options). + +%% @doc Unary RPC +-spec generate_error(route_guide_pb:empty()) -> + {ok, route_guide_pb:empty(), grpcbox:metadata()} | grpcbox_stream:grpc_error_response(). +generate_error(Input) -> + generate_error(ctx:new(), Input, #{}). + +-spec generate_error(ctx:t() | route_guide_pb:empty(), route_guide_pb:empty() | grpcbox_client:options()) -> + {ok, route_guide_pb:empty(), grpcbox:metadata()} | grpcbox_stream:grpc_error_response(). +generate_error(Ctx, Input) when ?is_ctx(Ctx) -> + generate_error(Ctx, Input, #{}); +generate_error(Input, Options) -> + generate_error(ctx:new(), Input, Options). + +-spec generate_error(ctx:t(), route_guide_pb:empty(), grpcbox_client:options()) -> + {ok, route_guide_pb:empty(), grpcbox:metadata()} | grpcbox_stream:grpc_error_response(). +generate_error(Ctx, Input, Options) -> + grpcbox_client:unary(Ctx, <<"/routeguide.RouteGuide/GenerateError">>, Input, ?DEF(empty, empty, <<"routeguide.Empty">>), Options). + +%% @doc +-spec streaming_generate_error(route_guide_pb:empty()) -> + {ok, grpcbox_client:stream()} | grpcbox_stream:grpc_error_response(). +streaming_generate_error(Input) -> + streaming_generate_error(ctx:new(), Input, #{}). + +-spec streaming_generate_error(ctx:t() | route_guide_pb:empty(), route_guide_pb:empty() | grpcbox_client:options()) -> + {ok, grpcbox_client:stream()} | grpcbox_stream:grpc_error_response(). +streaming_generate_error(Ctx, Input) when ?is_ctx(Ctx) -> + streaming_generate_error(Ctx, Input, #{}); +streaming_generate_error(Input, Options) -> + streaming_generate_error(ctx:new(), Input, Options). + +-spec streaming_generate_error(ctx:t(), route_guide_pb:empty(), grpcbox_client:options()) -> + {ok, grpcbox_client:stream()} | grpcbox_stream:grpc_error_response(). +streaming_generate_error(Ctx, Input, Options) -> + grpcbox_client:stream(Ctx, <<"/routeguide.RouteGuide/StreamingGenerateError">>, Input, ?DEF(empty, empty, <<"routeguide.Empty">>), Options). +