diff --git a/generator/internal/language/rusttemplate.go b/generator/internal/language/rusttemplate.go index 0cab02f16..714f0c74f 100644 --- a/generator/internal/language/rusttemplate.go +++ b/generator/internal/language/rusttemplate.go @@ -44,6 +44,9 @@ type RustTemplateData struct { NotForPublication bool HasFeatures bool Features []string + // When bootstrapping the well-known types crate the templates add some + // ad-hoc code. + IsWktCrate bool } type RustService struct { @@ -201,6 +204,7 @@ func newRustTemplateData(model *api.API, c *rustCodec, outdir string) (*RustTemp }), NameToLower: strings.ToLower(model.Name), NotForPublication: c.doNotPublish, + IsWktCrate: c.sourceSpecificationPackageName == "google.protobuf", } // Determine if any service has an LRO. for _, s := range data.Services { diff --git a/generator/internal/language/templates/rust/mod/mod.rs.mustache b/generator/internal/language/templates/rust/mod/mod.rs.mustache index 68a71ea7e..4d166ff1d 100644 --- a/generator/internal/language/templates/rust/mod/mod.rs.mustache +++ b/generator/internal/language/templates/rust/mod/mod.rs.mustache @@ -22,6 +22,12 @@ limitations under the License. #![allow(rustdoc::invalid_html_tags)] {{! We use explicit links because it is easier to generate the code with them. }} #![allow(rustdoc::redundant_explicit_links)] +{{#IsWktCrate}} +{{! +This file is used to bootstrap the `gcp-sdk-wkt` crate. In all other crates +`wkt` is well-defined and refers to said crate.}} +use crate as wkt; +{{/IsWktCrate}} {{#Messages}} {{> message}} {{/Messages}} diff --git a/generator/internal/sidekick/sidekick_test.go b/generator/internal/sidekick/sidekick_test.go index 6cec5f842..5d8cb6abb 100644 --- a/generator/internal/sidekick/sidekick_test.go +++ b/generator/internal/sidekick/sidekick_test.go @@ -198,6 +198,49 @@ func TestRustModuleFromProtobuf(t *testing.T) { } } +func TestRustBootstrapWkt(t *testing.T) { + type TestConfig struct { + Source string + ServiceConfig string + Name string + ExtraOptions map[string]string + } + configs := []TestConfig{ + { + Source: "google/protobuf/source_context.proto", + Name: "wkt", + ExtraOptions: map[string]string{ + "module-path": "crate", + }, + }, + } + + for _, config := range configs { + cmdLine := &CommandLine{ + Command: []string{}, + ProjectRoot: projectRoot, + SpecificationFormat: "protobuf", + SpecificationSource: config.Source, + Source: map[string]string{ + "googleapis-root": testdataDir, + }, + Language: "rust", + Output: path.Join(testdataDir, "rust/protobuf/golden/wkt/generated", config.Name), + Codec: map[string]string{ + "copyright-year": "2025", + "generate-module": "true", + }, + } + for k, v := range config.ExtraOptions { + cmdLine.Codec[k] = v + } + cmdGenerate, _, _ := cmdSidekick.lookup([]string{"generate"}) + if err := runCommand(cmdGenerate, cmdLine); err != nil { + t.Fatal(err) + } + } +} + func TestGoFromProtobuf(t *testing.T) { var outDir = fmt.Sprintf("%s/go/protobuf/golden", testdataDir) type TestConfig struct { diff --git a/generator/testdata/google/protobuf/source_context.proto b/generator/testdata/google/protobuf/source_context.proto new file mode 100644 index 000000000..135f50fea --- /dev/null +++ b/generator/testdata/google/protobuf/source_context.proto @@ -0,0 +1,48 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +syntax = "proto3"; + +package google.protobuf; + +option java_package = "com.google.protobuf"; +option java_outer_classname = "SourceContextProto"; +option java_multiple_files = true; +option objc_class_prefix = "GPB"; +option csharp_namespace = "Google.Protobuf.WellKnownTypes"; +option go_package = "google.golang.org/protobuf/types/known/sourcecontextpb"; + +// `SourceContext` represents information about the source of a +// protobuf element, like the file in which it is defined. +message SourceContext { + // The path-qualified name of the .proto file that contained the associated + // protobuf element. For example: `"google/protobuf/source_context.proto"`. + string file_name = 1; +} diff --git a/generator/testdata/rust/protobuf/golden/wkt/generated/wkt/.sidekick.toml b/generator/testdata/rust/protobuf/golden/wkt/generated/wkt/.sidekick.toml new file mode 100644 index 000000000..2e2d31563 --- /dev/null +++ b/generator/testdata/rust/protobuf/golden/wkt/generated/wkt/.sidekick.toml @@ -0,0 +1,26 @@ +# Copyright 2025 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +[general] +language = 'rust' +specification-format = 'protobuf' +specification-source = 'google/protobuf/source_context.proto' + +[source] +googleapis-root = 'testdata' + +[codec] +copyright-year = '2025' +generate-module = 'true' +module-path = 'crate' diff --git a/generator/testdata/rust/protobuf/golden/wkt/generated/wkt/mod.rs b/generator/testdata/rust/protobuf/golden/wkt/generated/wkt/mod.rs new file mode 100755 index 000000000..350cebeac --- /dev/null +++ b/generator/testdata/rust/protobuf/golden/wkt/generated/wkt/mod.rs @@ -0,0 +1,48 @@ +// Copyright 2025 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// Code generated by sidekick. DO NOT EDIT. + +#![allow(rustdoc::invalid_html_tags)] +#![allow(rustdoc::redundant_explicit_links)] +use crate as wkt; + +/// `SourceContext` represents information about the source of a +/// protobuf element, like the file in which it is defined. +#[serde_with::serde_as] +#[derive(Clone, Debug, Default, PartialEq, serde::Deserialize, serde::Serialize)] +#[serde(default, rename_all = "camelCase")] +#[non_exhaustive] +pub struct SourceContext { + + /// The path-qualified name of the .proto file that contained the associated + /// protobuf element. For example: `"google/protobuf/source_context.proto"`. + #[serde(skip_serializing_if = "std::string::String::is_empty")] + pub file_name: std::string::String, +} + +impl SourceContext { + + /// Sets the value of `file_name`. + pub fn set_file_name>(mut self, v: T) -> Self { + self.file_name = v.into(); + self + } +} + +impl wkt::message::Message for SourceContext { + fn typename() -> &'static str { + "type.googleapis.com/google.protobuf.SourceContext" + } +}