)]}'
{
  "commit": "d0e31c5af2a872e3f4473af941cad1e7ce36dbdb",
  "tree": "a2e870f6b3b1102fb875242107a229dd7ff966fa",
  "parents": [
    "237204539f91fc664a053a723fc1f1d57f2757ac"
  ],
  "author": {
    "name": "Protobuf Team Bot",
    "email": "protobuf-github-bot@google.com",
    "time": "Thu Oct 08 20:25:33 2026 -0700"
  },
  "committer": {
    "name": "Copybara-Service",
    "email": "copybara-worker@google.com",
    "time": "Thu Nov 05 08:04:42 2026 -0800"
  },
  "message": "Give Rust proto enums name(), from_name() and EnumValueNames, except under Lite.\n\nEvery other protobuf language converts an enum value to and from its .proto\nname: C++ has `Foo_Name` and `Foo_Parse`, Java `getValueDescriptor().getName()`\nand `valueOf`, Python `Name` and `Value`, Go `String()` and `Foo_value`. Rust has\nneither. The generator already emits every value name into each binary through\nthe private `constant_name()` that backs `Debug`, but callers can\u0027t reach it,\nand it returns the prefix-stripped Rust constant name (`NotFound`) rather than\nthe .proto name (`STATUS_NOT_FOUND`).\n\nRust code that has to produce or accept the same strings as other languages\n(logs, metric labels, config files, flags, and text formats that carry enum\nnames) therefore hand-writes a two-way match for each enum, which drifts\nwhenever a value is added to the .proto file. Generic libraries can\u0027t do it at\nall, since there is nothing to call through `T: Enum`.\n\nAdd `pub const fn name(self) -\u003e Option\u003c\u0026\u0027static str\u003e` and\n`pub fn from_name(\u0026str) -\u003e Option\u003cSelf\u003e` to the inherent impl generated for each\nenum. Both use the .proto names. For an aliased number, `name()` returns the\nfirst declared name, like `EnumDescriptor::FindValueByNumber`, and `from_name()`\naccepts every alias. `name()` returns `None` for an unknown value of an open\nenum. `name()` is a generated `match` on the number. `from_name()` binary-searches\na `(name, number)` table, aliases included, that the generator sorts by name, as\nC++ lite does, so lookups stay O(log n) for large enums; the search is a shared\nruntime helper, so each enum only adds its table. Both work the same on the C++\nand upb kernels.\n\nAdd a `protobuf::EnumValueNames` trait, with `Enum` as its supertrait, that each\nsuch enum implements by forwarding to the inherent functions, so that generic\ncode bounded by `T: EnumValueNames` can convert any of them without knowing its\ntype. The trait method isn\u0027t `const`, since stable Rust has no `const` trait\nmethods; the inherent `const fn` remains for constant contexts. Method calls and\n`Type::name` paths on a concrete enum resolve to the inherent functions, which\ntake precedence over the trait\u0027s.\n\nLite and mobile builds must not embed value names, which leak internal\nidentifiers from shipped binaries (Java on Android has the getter, but\nR8/ProGuard flags its use). So, as `HasReflectionSupport()` does for messages,\nenums from `optimize_for \u003d LITE_RUNTIME` files, and every enum when the lite\nruntime is forced, get neither the functions nor `EnumValueNames`: code that\nneeds the names fails to compile with them instead of retaining the names.\nKeeping the names out of `Enum` itself is what allows this, since every enum\nimplements `Enum`.\n\nNeither name can collide with a value constant, because those are always\nUpperCamelCase; the same reasoning already permits `constant_name()` and\n`number()`. Code that calls a user-defined trait method named `name` or\n`from_name` on a generated enum would now resolve to the inherent method.\n\n`enum_test` covers the functions and `EnumValueNames`, including every name of\nan enum whose names are declared out of order, and skips them when the lite\nruntime is forced. The new `lite_enum_test`, on both kernels, checks that an\n`optimize_for \u003d LITE_RUNTIME` enum doesn\u0027t implement `EnumValueNames`, and that\nother enums do unless the lite runtime is forced.\n\nPiperOrigin-RevId: 996243501\n",
  "tree_diff": [
    {
      "type": "modify",
      "old_id": "e03e403eb11503c4519aa988c61f9c13b5a89f75",
      "old_mode": 33188,
      "old_path": "rust/enum.rs",
      "new_id": "2232af21659c44a7000392662a508419d4dd3834",
      "new_mode": 33188,
      "new_path": "rust/enum.rs"
    },
    {
      "type": "modify",
      "old_id": "047684a4c35123cba871d15ccb0625ca6bb2c04c",
      "old_mode": 33188,
      "old_path": "rust/internal.rs",
      "new_id": "07e10cdbd199eb0c3260b17a14ebc544b8105cf1",
      "new_mode": 33188,
      "new_path": "rust/internal.rs"
    },
    {
      "type": "modify",
      "old_id": "4b3573a751ce5a6384bf0dd79206bc66b8f443a0",
      "old_mode": 33188,
      "old_path": "rust/release_crates/protobuf_tests/build.rs",
      "new_id": "6b947da963ee6325345dd86bf95f4033b90aaa1e",
      "new_mode": 33188,
      "new_path": "rust/release_crates/protobuf_tests/build.rs"
    },
    {
      "type": "modify",
      "old_id": "a8a5370d99b652c66a52b5853ec1727cdff758a4",
      "old_mode": 33188,
      "old_path": "rust/release_crates/protobuf_tests/tests/protos/mod.rs",
      "new_id": "f8d68686db35fbb4e14ffd199583561a16c00993",
      "new_mode": 33188,
      "new_path": "rust/release_crates/protobuf_tests/tests/protos/mod.rs"
    },
    {
      "type": "modify",
      "old_id": "680369e5df26856468cc6e63e582cb7d852b510f",
      "old_mode": 33188,
      "old_path": "rust/shared.rs",
      "new_id": "349b7d000625e7f5a0a621bf8e83efc8924cdd3f",
      "new_mode": 33188,
      "new_path": "rust/shared.rs"
    },
    {
      "type": "modify",
      "old_id": "67ebc3ce2b862610fe43bf5582bc9318767a7780",
      "old_mode": 33188,
      "old_path": "rust/test/BUILD",
      "new_id": "adffcdd0fc0b3b2b6225bbfaec93918b1f13ee12",
      "new_mode": 33188,
      "new_path": "rust/test/BUILD"
    },
    {
      "type": "add",
      "old_id": "0000000000000000000000000000000000000000",
      "old_mode": 0,
      "old_path": "/dev/null",
      "new_id": "490c96ee71ec2242f692019d949f4d69c4cc66fb",
      "new_mode": 33188,
      "new_path": "rust/test/lite_enums.proto"
    },
    {
      "type": "modify",
      "old_id": "f8e56cb23de251b5e607728fed61696a5dcf2734",
      "old_mode": 33188,
      "old_path": "rust/test/shared/BUILD",
      "new_id": "ffa688e4d71bec9571146f2809758d09cb2f5ac5",
      "new_mode": 33188,
      "new_path": "rust/test/shared/BUILD"
    },
    {
      "type": "modify",
      "old_id": "951d2be00deac760e5040a9670d64f9bb3a07ec3",
      "old_mode": 33188,
      "old_path": "rust/test/shared/enum_test.rs",
      "new_id": "93fc7424524f36a09d9d7c36b2c4335cf8196fba",
      "new_mode": 33188,
      "new_path": "rust/test/shared/enum_test.rs"
    },
    {
      "type": "add",
      "old_id": "0000000000000000000000000000000000000000",
      "old_mode": 0,
      "old_path": "/dev/null",
      "new_id": "13fd8b19fdc6866917fceb037b71141581e828fe",
      "new_mode": 33188,
      "new_path": "rust/test/shared/lite_enum_test.rs"
    },
    {
      "type": "modify",
      "old_id": "ffedc967ae16deed9aefb234bce21f37cdae3f94",
      "old_mode": 33188,
      "old_path": "src/google/protobuf/compiler/rust/enum.cc",
      "new_id": "ce49cc60a107a84988de6fac793bcfdd5278282a",
      "new_mode": 33188,
      "new_path": "src/google/protobuf/compiler/rust/enum.cc"
    }
  ]
}
