• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Protocol Buffers - Google's data interchange format
2 // Copyright 2023 Google LLC.  All rights reserved.
3 //
4 // Use of this source code is governed by a BSD-style
5 // license that can be found in the LICENSE file or at
6 // https://developers.google.com/open-source/licenses/bsd
7 
8 #include "google/protobuf/compiler/rust/context.h"
9 
10 #include <string>
11 #include <utility>
12 #include <vector>
13 
14 #include "absl/algorithm/container.h"
15 #include "absl/status/status.h"
16 #include "absl/status/statusor.h"
17 #include "absl/strings/string_view.h"
18 #include "absl/strings/substitute.h"
19 #include "google/protobuf/compiler/code_generator.h"
20 #include "google/protobuf/descriptor.h"
21 
22 namespace google {
23 namespace protobuf {
24 namespace compiler {
25 namespace rust {
26 static constexpr std::pair<absl::string_view, absl::string_view> kMagicValue = {
27     "experimental-codegen",
28     "enabled",
29 };
30 
Parse(absl::string_view param)31 absl::StatusOr<Options> Options::Parse(absl::string_view param) {
32   std::vector<std::pair<std::string, std::string>> args;
33   ParseGeneratorParameter(param, &args);
34 
35   bool has_experimental_value = absl::c_any_of(
36       args, [](std::pair<absl::string_view, absl::string_view> pair) {
37         return pair == kMagicValue;
38       });
39 
40   if (!has_experimental_value) {
41     return absl::InvalidArgumentError(
42         "The Rust codegen is highly experimental. Future versions will break "
43         "existing code. Use at your own risk. You can opt-in by passing "
44         "'experimental-codegen=enabled' to '--rust_opt'.");
45   }
46 
47   Options opts;
48 
49   auto kernel_arg =
50       absl::c_find_if(args, [](auto& arg) { return arg.first == "kernel"; });
51   if (kernel_arg == args.end()) {
52     return absl::InvalidArgumentError(
53         "Mandatory option `kernel` missing, please specify `cpp` or "
54         "`upb`.");
55   }
56 
57   if (kernel_arg->second == "upb") {
58     opts.kernel = Kernel::kUpb;
59   } else if (kernel_arg->second == "cpp") {
60     opts.kernel = Kernel::kCpp;
61   } else {
62     return absl::InvalidArgumentError(
63         absl::Substitute("Unknown kernel `$0`, please specify `cpp` or "
64                          "`upb`.",
65                          kernel_arg->second));
66   }
67 
68   auto mapping_arg = absl::c_find_if(
69       args, [](auto& arg) { return arg.first == "bazel_crate_mapping"; });
70   if (mapping_arg != args.end()) {
71     opts.mapping_file_path = mapping_arg->second;
72   }
73 
74   auto strip_nonfunctional_codegen_arg = absl::c_find_if(args, [](auto& arg) {
75     return arg.first == "experimental_strip_nonfunctional_codegen";
76   });
77   if (strip_nonfunctional_codegen_arg != args.end()) {
78     opts.strip_nonfunctional_codegen = true;
79   }
80 
81   return opts;
82 }
83 
IsInCurrentlyGeneratingCrate(Context & ctx,const FileDescriptor & file)84 bool IsInCurrentlyGeneratingCrate(Context& ctx, const FileDescriptor& file) {
85   return ctx.generator_context().is_file_in_current_crate(file);
86 }
87 
IsInCurrentlyGeneratingCrate(Context & ctx,const Descriptor & message)88 bool IsInCurrentlyGeneratingCrate(Context& ctx, const Descriptor& message) {
89   return IsInCurrentlyGeneratingCrate(ctx, *message.file());
90 }
91 
IsInCurrentlyGeneratingCrate(Context & ctx,const EnumDescriptor & enum_)92 bool IsInCurrentlyGeneratingCrate(Context& ctx, const EnumDescriptor& enum_) {
93   return IsInCurrentlyGeneratingCrate(ctx, *enum_.file());
94 }
95 
96 }  // namespace rust
97 }  // namespace compiler
98 }  // namespace protobuf
99 }  // namespace google
100