Implement bp2build converter for rust_binary

Test: go test
Bug: 295910295
Change-Id: Ieb18d9071f28e53a0463614594cee0fd755b7b3c
diff --git a/bp2build/rust_binary_conversion_test.go b/bp2build/rust_binary_conversion_test.go
new file mode 100644
index 0000000..3364401
--- /dev/null
+++ b/bp2build/rust_binary_conversion_test.go
@@ -0,0 +1,74 @@
+package bp2build
+
+import (
+	"android/soong/android"
+	"android/soong/rust"
+	"testing"
+)
+
+func runRustBinaryTestCase(t *testing.T, tc Bp2buildTestCase) {
+	t.Helper()
+	RunBp2BuildTestCase(t, registerRustBinaryModuleTypes, tc)
+}
+
+func registerRustBinaryModuleTypes(ctx android.RegistrationContext) {
+	ctx.RegisterModuleType("rust_binary_host", rust.RustBinaryHostFactory)
+	ctx.RegisterModuleType("rust_library_host", rust.RustLibraryHostFactory)
+	ctx.RegisterModuleType("rust_proc_macro", rust.ProcMacroFactory)
+
+}
+
+func TestRustBinaryHost(t *testing.T) {
+	runRustBinaryTestCase(t, Bp2buildTestCase{
+		Dir:       "external/rust/crates/foo",
+		Blueprint: "",
+		Filesystem: map[string]string{
+			"external/rust/crates/foo/src/lib.rs":    "",
+			"external/rust/crates/foo/src/helper.rs": "",
+			"external/rust/crates/foo/Android.bp": `
+rust_binary_host {
+	name: "libfoo",
+	crate_name: "foo",
+	srcs: ["src/main.rs"],
+	edition: "2021",
+	features: ["bah-enabled"],
+	cfgs: ["baz"],
+	rustlibs: ["libbar"],
+	proc_macros: ["libbah"],
+    bazel_module: { bp2build_available: true },
+}
+`,
+			"external/rust/crates/bar/Android.bp": `
+rust_library_host {
+	name: "libbar",
+	crate_name: "bar",
+	srcs: ["src/lib.rs"],
+    bazel_module: { bp2build_available: true },
+}
+`,
+			"external/rust/crates/bah/Android.bp": `
+rust_proc_macro {
+	name: "libbah",
+	crate_name: "bah",
+	srcs: ["src/lib.rs"],
+    bazel_module: { bp2build_available: true },
+}
+`,
+		},
+		ExpectedBazelTargets: []string{
+			makeBazelTargetHostOrDevice("rust_binary", "libfoo", AttrNameToString{
+				"crate_name": `"foo"`,
+				"srcs": `[
+        "src/helper.rs",
+        "src/lib.rs",
+    ]`,
+				"deps":            `["//external/rust/crates/bar:libbar"]`,
+				"proc_macro_deps": `["//external/rust/crates/bah:libbah"]`,
+				"edition":         `"2021"`,
+				"crate_features":  `["bah-enabled"]`,
+				"rustc_flags":     `["--cfg=baz"]`,
+			}, android.HostSupported),
+		},
+	},
+	)
+}
diff --git a/rust/binary.go b/rust/binary.go
index e6f1539..1e24beb 100644
--- a/rust/binary.go
+++ b/rust/binary.go
@@ -16,6 +16,8 @@
 
 import (
 	"android/soong/android"
+	"android/soong/bazel"
+	"fmt"
 )
 
 func init() {
@@ -60,6 +62,8 @@
 func NewRustBinary(hod android.HostOrDeviceSupported) (*Module, *binaryDecorator) {
 	module := newModule(hod, android.MultilibFirst)
 
+	android.InitBazelModule(module)
+
 	binary := &binaryDecorator{
 		baseCompiler: NewBaseCompiler("bin", "", InstallInSystem),
 	}
@@ -183,3 +187,88 @@
 func (binary *binaryDecorator) testBinary() bool {
 	return false
 }
+
+type rustBinaryLibraryAttributes struct {
+	Srcs            bazel.LabelListAttribute
+	Compile_data    bazel.LabelListAttribute
+	Crate_name      bazel.StringAttribute
+	Edition         bazel.StringAttribute
+	Crate_features  bazel.StringListAttribute
+	Deps            bazel.LabelListAttribute
+	Proc_macro_deps bazel.LabelListAttribute
+	Rustc_flags     bazel.StringListAttribute
+}
+
+func binaryBp2build(ctx android.TopDownMutatorContext, m *Module) {
+	binary := m.compiler.(*binaryDecorator)
+
+	var srcs bazel.LabelList
+	var compileData bazel.LabelList
+
+	if binary.baseCompiler.Properties.Srcs[0] == "src/main.rs" {
+		srcs = android.BazelLabelForModuleSrc(ctx, []string{"src/**/*.rs"})
+		compileData = android.BazelLabelForModuleSrc(
+			ctx,
+			[]string{
+				"src/**/*.proto",
+				"examples/**/*.rs",
+				"**/*.md",
+				"templates/**/*.template",
+			},
+		)
+	} else {
+		srcs = android.BazelLabelForModuleSrc(ctx, binary.baseCompiler.Properties.Srcs)
+	}
+
+	deps := android.BazelLabelForModuleDeps(ctx, append(
+		binary.baseCompiler.Properties.Rustlibs,
+	))
+
+	procMacroDeps := android.BazelLabelForModuleDeps(ctx, binary.baseCompiler.Properties.Proc_macros)
+
+	var rustcFLags []string
+	for _, cfg := range binary.baseCompiler.Properties.Cfgs {
+		rustcFLags = append(rustcFLags, fmt.Sprintf("--cfg=%s", cfg))
+	}
+
+	attrs := &rustBinaryLibraryAttributes{
+		Srcs: bazel.MakeLabelListAttribute(
+			srcs,
+		),
+		Compile_data: bazel.MakeLabelListAttribute(
+			compileData,
+		),
+		Crate_name: bazel.StringAttribute{
+			Value: &binary.baseCompiler.Properties.Crate_name,
+		},
+		Edition: bazel.StringAttribute{
+			Value: binary.baseCompiler.Properties.Edition,
+		},
+		Crate_features: bazel.StringListAttribute{
+			Value: binary.baseCompiler.Properties.Features,
+		},
+		Deps: bazel.MakeLabelListAttribute(
+			deps,
+		),
+		Proc_macro_deps: bazel.MakeLabelListAttribute(
+			procMacroDeps,
+		),
+		Rustc_flags: bazel.StringListAttribute{
+			Value: append(
+				rustcFLags,
+				binary.baseCompiler.Properties.Flags...,
+			),
+		},
+	}
+
+	ctx.CreateBazelTargetModule(
+		bazel.BazelTargetModuleProperties{
+			Rule_class:        "rust_binary",
+			Bzl_load_location: "@rules_rust//rust:defs.bzl",
+		},
+		android.CommonAttributes{
+			Name: m.Name(),
+		},
+		attrs,
+	)
+}
diff --git a/rust/rust.go b/rust/rust.go
index 121d9b4..9494507 100644
--- a/rust/rust.go
+++ b/rust/rust.go
@@ -1850,6 +1850,8 @@
 		libraryBp2build(ctx, m)
 	} else if ctx.ModuleType() == "rust_proc_macro" {
 		procMacroBp2build(ctx, m)
+	} else if ctx.ModuleType() == "rust_binary_host" {
+		binaryBp2build(ctx, m)
 	} else {
 		ctx.MarkBp2buildUnconvertible(bp2build_metrics_proto.UnconvertedReasonType_TYPE_UNSUPPORTED, "")
 	}