Fix naming according to the Rust styleguide. am: 192e0bbc0f

Original change: https://android-review.googlesource.com/c/platform/system/tools/sysprop/+/2743333

Change-Id: Iefb05e2492eafe781684d18306896fd789c48296
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
diff --git a/Common.cpp b/Common.cpp
index ec7d120..fc64099 100644
--- a/Common.cpp
+++ b/Common.cpp
@@ -360,3 +360,34 @@
   return (isdigit(name[0]) ? "_" : "") +
          std::regex_replace(name, kRegexAllowed, "_");
 }
+
+std::string SnakeCaseToCamelCase(const std::string& s) {
+  std::string result;
+  for (int i = 0; i < s.size(); ++i) {
+    if (s[i] == '_') continue;
+    char current = tolower(s[i]);  // Handle screaming snake case.
+    if (i == 0 || s[i - 1] == '_') {
+      current = toupper(current);
+    }
+    result += current;
+  }
+  return result;
+}
+
+std::string CamelCaseToSnakeCase(const std::string& s) {
+  // Desired behaviour: "CurrentAPIVersion" -> "current_api_version".
+  std::string result;
+  for (int i = 0; i < s.size(); ++i) {
+    char current = s[i];
+    char prev = (i > 0) ? s[i - 1] : 0;
+    char next = (i < s.size() - 1) ? s[i + 1] : 0;
+    if (prev && isupper(prev) && (!next || isupper(next) || !isalpha(next))) {
+      current = tolower(current);
+    }
+    if (i > 0 && isupper(current) && result[result.size() - 1] != '_') {
+      result += '_';
+    }
+    result += tolower(current);
+  }
+  return result;
+}
\ No newline at end of file
diff --git a/RustGen.cpp b/RustGen.cpp
index 5982f65..4390db5 100644
--- a/RustGen.cpp
+++ b/RustGen.cpp
@@ -192,12 +192,7 @@
 
 std::string GetRustEnumType(const sysprop::Property& prop) {
   std::string result = ApiNameToIdentifier(prop.api_name());
-  for (int i = 0; i < result.size(); ++i) {
-    if (i == 0 || result[i - 1] == '_') {
-      result[i] = toupper(result[i]);
-    }
-  }
-  return std::regex_replace(result, std::regex{"_"}, "") + "Values";
+  return SnakeCaseToCamelCase(result) + "Values";
 }
 
 std::string GetRustReturnType(const sysprop::Property& prop) {
@@ -313,14 +308,13 @@
       }
       return "gen_parsers_and_formatters::format_bool";
     case sysprop::String:
-      return "gen_parsers_and_formatters::format";
     case sysprop::Integer:
     case sysprop::UInt:
     case sysprop::Long:
     case sysprop::ULong:
     case sysprop::Double:
     case sysprop::Enum:
-      return "gen_parsers_and_formatters::format_value";
+      return "gen_parsers_and_formatters::format";
     case sysprop::BooleanList:
       if (prop.integer_as_bool()) {
         return "gen_parsers_and_formatters::format_bool_list_as_int";
@@ -351,7 +345,8 @@
     const sysprop::Property& prop = props.prop(i);
     if (prop.scope() > scope) continue;
 
-    std::string prop_id = ApiNameToIdentifier(prop.api_name());
+    std::string prop_id =
+        CamelCaseToSnakeCase(ApiNameToIdentifier(prop.api_name()));
 
     // Create enum.
     if (prop.type() == sysprop::Enum || prop.type() == sysprop::EnumList) {
@@ -364,13 +359,13 @@
       writer.Write("pub enum %s {\n", enum_type.c_str());
       writer.Indent();
       for (const std::string& value : values) {
-        writer.Write("%s,\n", ToUpper(value).c_str());
+        writer.Write("%s,\n", SnakeCaseToCamelCase(value).c_str());
       }
       writer.Dedent();
       writer.Write("}\n\n");
 
       // Enum parser.
-      writer.Write("impl FromStr for %s {\n", enum_type.c_str());
+      writer.Write("impl std::str::FromStr for %s {\n", enum_type.c_str());
       writer.Indent();
       writer.Write("type Err = String;\n\n");
       writer.Write("fn from_str(s: &str) -> Result<Self, Self::Err> {\n");
@@ -379,7 +374,7 @@
       writer.Indent();
       for (const std::string& value : values) {
         writer.Write("\"%s\" => Ok(%s::%s),\n", value.c_str(),
-                     enum_type.c_str(), ToUpper(value).c_str());
+                     enum_type.c_str(), SnakeCaseToCamelCase(value).c_str());
       }
       writer.Write("_ => Err(format!(\"'{}' cannot be parsed for %s\", s)),\n",
                    enum_type.c_str());
@@ -400,7 +395,7 @@
       writer.Indent();
       for (const std::string& value : values) {
         writer.Write("%s::%s => write!(f, \"%s\"),\n", enum_type.c_str(),
-                     ToUpper(value).c_str(), value.c_str());
+                     SnakeCaseToCamelCase(value).c_str(), value.c_str());
       }
       writer.Write("_ => Err(fmt::Error),\n");
       writer.Dedent();
diff --git a/include/Common.h b/include/Common.h
index 8ad6fb1..7d3a2ad 100644
--- a/include/Common.h
+++ b/include/Common.h
@@ -32,3 +32,5 @@
 android::base::Result<sysprop::SyspropLibraryApis> ParseApiFile(
     const std::string& file_path);
 std::string ToUpper(std::string str);
+std::string CamelCaseToSnakeCase(const std::string& str);
+std::string SnakeCaseToCamelCase(const std::string& str);
diff --git a/tests/CommonTest.cpp b/tests/CommonTest.cpp
new file mode 100644
index 0000000..cd343f7
--- /dev/null
+++ b/tests/CommonTest.cpp
@@ -0,0 +1,39 @@
+/* Copyright (C) 2023 The Android Open Source Project
+ *
+ * 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
+ *
+ *      http://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.
+ */
+
+#include <android-base/test_utils.h>
+#include <gtest/gtest.h>
+
+#include "Common.h"
+
+TEST(SyspropTest, CamelToSnakeTest) {
+  EXPECT_EQ(CamelCaseToSnakeCase("CurrentAPIVersion"), "current_api_version");
+  EXPECT_EQ(CamelCaseToSnakeCase("CurrentAPI"), "current_api");
+  EXPECT_EQ(CamelCaseToSnakeCase("APIVersion"), "api_version");
+  EXPECT_EQ(CamelCaseToSnakeCase("API"), "api");
+  EXPECT_EQ(CamelCaseToSnakeCase("API2"), "api2");
+  EXPECT_EQ(CamelCaseToSnakeCase("SomeRandomCamelCase"),
+            "some_random_camel_case");
+  EXPECT_EQ(CamelCaseToSnakeCase("snake_case"), "snake_case");
+  EXPECT_EQ(CamelCaseToSnakeCase("Strange_Camel_Case"), "strange_camel_case");
+}
+
+TEST(SyspropTest, SnakeToCamelTest) {
+  EXPECT_EQ(SnakeCaseToCamelCase("current_api_version"), "CurrentApiVersion");
+  EXPECT_EQ(SnakeCaseToCamelCase("random"), "Random");
+  EXPECT_EQ(SnakeCaseToCamelCase("SCREAMING_SNAKE_CASE_100"),
+            "ScreamingSnakeCase100");
+  EXPECT_EQ(SnakeCaseToCamelCase("double__underscore"), "DoubleUnderscore");
+}
\ No newline at end of file
diff --git a/tests/RustGenTest.cpp b/tests/RustGenTest.cpp
index e840005..ce58c0b 100644
--- a/tests/RustGenTest.cpp
+++ b/tests/RustGenTest.cpp
@@ -150,7 +150,7 @@
 
 /// Sets the value of the property 'android.test_int', returns 'Ok' if successful.
 pub fn set_test_int(v: i32) -> Result<()> {
-    let value = gen_parsers_and_formatters::format_value(&v);
+    let value = gen_parsers_and_formatters::format(&v);
     system_properties::write("android.test_int", value.as_str()).map_err(SysPropError::SetError)
 }
 
@@ -171,7 +171,7 @@
 }
 
 /// Returns the value of the property 'ro.android.test.b' if set.
-pub fn test_BOOLeaN() -> Result<Option<bool>> {
+pub fn test_boo_lea_n() -> Result<Option<bool>> {
     let result = match system_properties::read("ro.android.test.b") {
         Err(e) => Err(SysPropError::FetchError(e)),
         Ok(Some(val)) => gen_parsers_and_formatters::parse_bool(val.as_str()).map_err(SysPropError::ParseError).map(Some),
@@ -181,7 +181,7 @@
 }
 
 /// Sets the value of the property 'ro.android.test.b', returns 'Ok' if successful.
-pub fn set_test_BOOLeaN(v: bool) -> Result<()> {
+pub fn set_test_boo_lea_n(v: bool) -> Result<()> {
     let value = gen_parsers_and_formatters::format_bool(&v);
     system_properties::write("ro.android.test.b", value.as_str()).map_err(SysPropError::SetError)
 }
@@ -198,7 +198,7 @@
 
 /// Sets the value of the property 'android_os_test-long', returns 'Ok' if successful.
 pub fn set_android_os_test_long(v: i64) -> Result<()> {
-    let value = gen_parsers_and_formatters::format_value(&v);
+    let value = gen_parsers_and_formatters::format(&v);
     system_properties::write("android_os_test-long", value.as_str()).map_err(SysPropError::SetError)
 }
 
@@ -290,7 +290,7 @@
 
 /// Sets the value of the property 'android.test_double', returns 'Ok' if successful.
 pub fn set_test_double(v: f64) -> Result<()> {
-    let value = gen_parsers_and_formatters::format_value(&v);
+    let value = gen_parsers_and_formatters::format(&v);
     system_properties::write("android.test_double", value.as_str()).map_err(SysPropError::SetError)
 }
 
@@ -306,7 +306,7 @@
 
 /// Sets the value of the property 'android.test_int', returns 'Ok' if successful.
 pub fn set_test_int(v: i32) -> Result<()> {
-    let value = gen_parsers_and_formatters::format_value(&v);
+    let value = gen_parsers_and_formatters::format(&v);
     system_properties::write("android.test_int", value.as_str()).map_err(SysPropError::SetError)
 }
 
@@ -337,7 +337,7 @@
     G,
 }
 
-impl FromStr for TestEnumValues {
+impl std::str::FromStr for TestEnumValues {
     type Err = String;
 
     fn from_str(s: &str) -> Result<Self, Self::Err> {
@@ -381,12 +381,12 @@
 
 /// Sets the value of the property 'android.test.enum', returns 'Ok' if successful.
 pub fn set_test_enum(v: TestEnumValues) -> Result<()> {
-    let value = gen_parsers_and_formatters::format_value(&v);
+    let value = gen_parsers_and_formatters::format(&v);
     system_properties::write("android.test.enum", value.as_str()).map_err(SysPropError::SetError)
 }
 
 /// Returns the value of the property 'ro.android.test.b' if set.
-pub fn test_BOOLeaN() -> Result<Option<bool>> {
+pub fn test_boo_lea_n() -> Result<Option<bool>> {
     let result = match system_properties::read("ro.android.test.b") {
         Err(e) => Err(SysPropError::FetchError(e)),
         Ok(Some(val)) => gen_parsers_and_formatters::parse_bool(val.as_str()).map_err(SysPropError::ParseError).map(Some),
@@ -396,7 +396,7 @@
 }
 
 /// Sets the value of the property 'ro.android.test.b', returns 'Ok' if successful.
-pub fn set_test_BOOLeaN(v: bool) -> Result<()> {
+pub fn set_test_boo_lea_n(v: bool) -> Result<()> {
     let value = gen_parsers_and_formatters::format_bool(&v);
     system_properties::write("ro.android.test.b", value.as_str()).map_err(SysPropError::SetError)
 }
@@ -413,7 +413,7 @@
 
 /// Sets the value of the property 'android_os_test-long', returns 'Ok' if successful.
 pub fn set_android_os_test_long(v: i64) -> Result<()> {
-    let value = gen_parsers_and_formatters::format_value(&v);
+    let value = gen_parsers_and_formatters::format(&v);
     system_properties::write("android_os_test-long", value.as_str()).map_err(SysPropError::SetError)
 }
 
@@ -469,19 +469,19 @@
 
 #[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Hash, Ord)]
 pub enum ElValues {
-    ENU,
-    MVA,
-    LUE,
+    Enu,
+    Mva,
+    Lue,
 }
 
-impl FromStr for ElValues {
+impl std::str::FromStr for ElValues {
     type Err = String;
 
     fn from_str(s: &str) -> Result<Self, Self::Err> {
         match s {
-            "enu" => Ok(ElValues::ENU),
-            "mva" => Ok(ElValues::MVA),
-            "lue" => Ok(ElValues::LUE),
+            "enu" => Ok(ElValues::Enu),
+            "mva" => Ok(ElValues::Mva),
+            "lue" => Ok(ElValues::Lue),
             _ => Err(format!("'{}' cannot be parsed for ElValues", s)),
         }
     }
@@ -490,9 +490,9 @@
 impl fmt::Display for ElValues {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         match self {
-            ElValues::ENU => write!(f, "enu"),
-            ElValues::MVA => write!(f, "mva"),
-            ElValues::LUE => write!(f, "lue"),
+            ElValues::Enu => write!(f, "enu"),
+            ElValues::Mva => write!(f, "mva"),
+            ElValues::Lue => write!(f, "lue"),
             _ => Err(fmt::Error),
         }
     }