Export ReverseSliceInPlace and ReverseSlice

... and add tests.

Test: TestReverseSliceInPlace, TestReverseSlice
Change-Id: I70f811207fdb2af891f7ef3fe19cbe5c7276135a
diff --git a/android/arch.go b/android/arch.go
index 4b4691b..152016c 100644
--- a/android/arch.go
+++ b/android/arch.go
@@ -1884,10 +1884,10 @@
 		buildTargets = filterMultilibTargets(targets, "lib64")
 		// Reverse the targets so that the first architecture can depend on the second
 		// architecture module in order to merge the outputs.
-		reverseSliceInPlace(buildTargets)
+		ReverseSliceInPlace(buildTargets)
 	case "darwin_universal_common_first":
 		archTargets := filterMultilibTargets(targets, "lib64")
-		reverseSliceInPlace(archTargets)
+		ReverseSliceInPlace(archTargets)
 		buildTargets = append(getCommonTargets(targets), archTargets...)
 	default:
 		return nil, fmt.Errorf(`compile_multilib must be "both", "first", "32", "64", "prefer32" or "first_prefer32" found %q`,
diff --git a/android/depset_generic.go b/android/depset_generic.go
index ae14d32..dcf133c 100644
--- a/android/depset_generic.go
+++ b/android/depset_generic.go
@@ -79,8 +79,8 @@
 	if order == TOPOLOGICAL {
 		// TOPOLOGICAL is implemented as a postorder traversal followed by reversing the output.
 		// Pre-reverse the inputs here so their order is maintained in the output.
-		directCopy = reverseSlice(direct)
-		transitiveCopy = reverseSlice(transitive)
+		directCopy = ReverseSlice(direct)
+		transitiveCopy = ReverseSlice(transitive)
 	} else {
 		directCopy = append([]T(nil), direct...)
 		transitiveCopy = append([]*DepSet[T](nil), transitive...)
@@ -194,7 +194,7 @@
 	})
 	list = firstUniqueFunc(list)
 	if d.reverse {
-		reverseSliceInPlace(list)
+		ReverseSliceInPlace(list)
 	}
 	return list
 }
diff --git a/android/util.go b/android/util.go
index 0080467..3eb8dcb 100644
--- a/android/util.go
+++ b/android/util.go
@@ -338,15 +338,19 @@
 	return in[0:writeIndex]
 }
 
-// reverseSliceInPlace reverses the elements of a slice in place.
-func reverseSliceInPlace[T any](in []T) {
+// ReverseSliceInPlace reverses the elements of a slice in place and returns it.
+func ReverseSliceInPlace[T any](in []T) []T {
 	for i, j := 0, len(in)-1; i < j; i, j = i+1, j-1 {
 		in[i], in[j] = in[j], in[i]
 	}
+	return in
 }
 
-// reverseSlice returns a copy of a slice in reverse order.
-func reverseSlice[T any](in []T) []T {
+// ReverseSlice returns a copy of a slice in reverse order.
+func ReverseSlice[T any](in []T) []T {
+	if in == nil {
+		return in
+	}
 	out := make([]T, len(in))
 	for i := 0; i < len(in); i++ {
 		out[i] = in[len(in)-1-i]
diff --git a/android/util_test.go b/android/util_test.go
index 0e28b56..20161e5 100644
--- a/android/util_test.go
+++ b/android/util_test.go
@@ -20,6 +20,7 @@
 	"strconv"
 	"strings"
 	"testing"
+	"unsafe"
 )
 
 var firstUniqueStringsTestCases = []struct {
@@ -754,3 +755,65 @@
 		})
 	}
 }
+
+var reverseTestCases = []struct {
+	name     string
+	in       []string
+	expected []string
+}{
+	{
+		name:     "nil",
+		in:       nil,
+		expected: nil,
+	},
+	{
+		name:     "empty",
+		in:       []string{},
+		expected: []string{},
+	},
+	{
+		name:     "one",
+		in:       []string{"one"},
+		expected: []string{"one"},
+	},
+	{
+		name:     "even",
+		in:       []string{"one", "two"},
+		expected: []string{"two", "one"},
+	},
+	{
+		name:     "odd",
+		in:       []string{"one", "two", "three"},
+		expected: []string{"three", "two", "one"},
+	},
+}
+
+func TestReverseSliceInPlace(t *testing.T) {
+	for _, testCase := range reverseTestCases {
+		t.Run(testCase.name, func(t *testing.T) {
+			slice := CopyOf(testCase.in)
+			slice2 := slice
+			ReverseSliceInPlace(slice)
+			if !reflect.DeepEqual(slice, testCase.expected) {
+				t.Errorf("expected %#v, got %#v", testCase.expected, slice)
+			}
+			if unsafe.SliceData(slice) != unsafe.SliceData(slice2) {
+				t.Errorf("expected slices to share backing array")
+			}
+		})
+	}
+}
+
+func TestReverseSlice(t *testing.T) {
+	for _, testCase := range reverseTestCases {
+		t.Run(testCase.name, func(t *testing.T) {
+			slice := ReverseSlice(testCase.in)
+			if !reflect.DeepEqual(slice, testCase.expected) {
+				t.Errorf("expected %#v, got %#v", testCase.expected, slice)
+			}
+			if slice != nil && unsafe.SliceData(testCase.in) == unsafe.SliceData(slice) {
+				t.Errorf("expected slices to have different backing arrays")
+			}
+		})
+	}
+}