blob: b4b6f367606a0d19148f30794f692ecfddb62b31 [file] [log] [blame]
// Protocol Buffers - Google's data interchange format
// Copyright 2023 Google LLC. All rights reserved.
//
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file or at
// https://developers.google.com/open-source/licenses/bsd
#include "google/protobuf/compiler/rust/context.h"
#include <string>
#include <utility>
#include <vector>
#include "absl/algorithm/container.h"
#include "absl/status/status.h"
#include "absl/status/statusor.h"
#include "absl/strings/string_view.h"
#include "absl/strings/substitute.h"
#include "google/protobuf/compiler/code_generator.h"
#include "google/protobuf/descriptor.h"
namespace google {
namespace protobuf {
namespace compiler {
namespace rust {
static constexpr std::pair<absl::string_view, absl::string_view> kMagicValue = {
"experimental-codegen",
"enabled",
};
absl::StatusOr<Options> Options::Parse(absl::string_view param) {
std::vector<std::pair<std::string, std::string>> args;
ParseGeneratorParameter(param, &args);
bool has_experimental_value = absl::c_any_of(
args, [](std::pair<absl::string_view, absl::string_view> pair) {
return pair == kMagicValue;
});
if (!has_experimental_value) {
return absl::InvalidArgumentError(
"The Rust codegen is highly experimental. Future versions will break "
"existing code. Use at your own risk. You can opt-in by passing "
"'experimental-codegen=enabled' to '--rust_opt'.");
}
Options opts;
auto kernel_arg =
absl::c_find_if(args, [](auto& arg) { return arg.first == "kernel"; });
if (kernel_arg == args.end()) {
return absl::InvalidArgumentError(
"Mandatory option `kernel` missing, please specify `cpp` or "
"`upb`.");
}
if (kernel_arg->second == "upb") {
opts.kernel = Kernel::kUpb;
} else if (kernel_arg->second == "cpp") {
opts.kernel = Kernel::kCpp;
} else {
return absl::InvalidArgumentError(
absl::Substitute("Unknown kernel `$0`, please specify `cpp` or "
"`upb`.",
kernel_arg->second));
}
auto mapping_arg = absl::c_find_if(
args, [](auto& arg) { return arg.first == "bazel_crate_mapping"; });
if (mapping_arg != args.end()) {
opts.mapping_file_path = mapping_arg->second;
}
return opts;
}
bool IsInCurrentlyGeneratingCrate(Context& ctx, const FileDescriptor& file) {
return ctx.generator_context().is_file_in_current_crate(file);
}
bool IsInCurrentlyGeneratingCrate(Context& ctx, const Descriptor& message) {
return IsInCurrentlyGeneratingCrate(ctx, *message.file());
}
bool IsInCurrentlyGeneratingCrate(Context& ctx, const EnumDescriptor& enum_) {
return IsInCurrentlyGeneratingCrate(ctx, *enum_.file());
}
} // namespace rust
} // namespace compiler
} // namespace protobuf
} // namespace google