Repository: tokio-rs/prost (language: rust)

Issue:
Document Enumerations
README says:

*All .proto enumeration types convert to the Rust i32 type. Additionally, each enumeration type gets a corresponding Rust enum type, with helper methods to convert i32 values to the enum type. The enum type isn't used directly as a field, because the Protobuf spec mandates that enumerations values are 'open', and decoding unrecognized enumeration values must be possible.*

It took me some (rather cheerless) time to discover that I can convert an enumeration like the one in the README example

```rust
    #[derive(Clone, Copy, Debug, PartialEq, Eq, Enumeration)]
    pub enum PhoneType {
        Mobile = 0,
        Home = 1,
        Work = 2,
    }
```

to the value this way:

```rust
PhoneType::Mobile as i32
```

However, for the opposite direction, I'm lost for good. How do I convert an i32 code to PhoneType? Where do I find those "helper methods to convert i32 values to the enum type"? I'd really appreciate an example in the README. Thank you.

Furthermore, what is the `#[derive(Enumeration)]` ? Can't find the Enumeration trait anywhere..
Document Enumerations
README says:

*All .proto enumeration types convert to the Rust i32 type. Additionally, each enumeration type gets a corresponding Rust enum type, with helper methods to convert i32 values to the enum type. The enum type isn't used directly as a field, because the Protobuf spec mandates that enumerations values are 'open', and decoding unrecognized enumeration values must be possible.*

It took me some (rather cheerless) time to discover that I can convert an enumeration like the one in the README example

```rust
    #[derive(Clone, Copy, Debug, PartialEq, Eq, Enumeration)]
    pub enum PhoneType {
        Mobile = 0,
        Home = 1,
        Work = 2,
    }
```

to the value this way:

```rust
PhoneType::Mobile as i32
```

However, for the opposite direction, I'm lost for good. How do I convert an i32 code to PhoneType? Where do I find those "helper methods to convert i32 values to the enum type"? I'd really appreciate an example in the README. Thank you.

Furthermore, what is the `#[derive(Enumeration)]` ? Can't find the Enumeration trait anywhere..


Discussion / hints:
Hi @dvtomas, thanks for opening this issue, I agree the docs should be improved in this area.  The ergonomic helpers for enums were added after I wrote that bit in the readme, and I never went back and filled it in.

Toward your immediate issue, the best way to see what's available is to run `rustdoc` on the types and see the methods which they expose.  In the case of a `PhoneType` enum, it will expose a pair of methods which help convert from `i32`:

```rust
impl PhoneType {
  pub fn is_valid(value: i32) -> bool;
  pub fn from_i32(value: i32) -> Option<PhoneType>;
}
```

You can see a concrete example [here](https://docs.rs/prost-types/0.2.3/prost_types/field/enum.Cardinality.html).

As for the `Enumeration` trait, there is actually no such thing.  `derive(Enumeration)` is a trick which allows prost to generate these methods for enum types, but there's no corresponding trait.

I'm going to leave this issue open to track improving the enum docs.
Forgot to mention - there are other helper methods as well.  Wherever an Enumeration is used as a field in a Message, the message will have an 'accessor' methods to get/set the value as the proper type.  For instance, the [`Field`](https://docs.rs/prost-types/0.2.3/prost_types/struct.Field.html) struct contains a `Cardinality` field and the following methods:

```rust
impl Field {
  pub fn cardinality(&self) -> Cardinality;
  pub fn set_cardinality(&mut self, value: Cardinality);
}
```

Note that the first of these will return the default value (the first variant if otherwise unspecified) if the `i32` value is out of range.
Thank you for the info! It's a neat trick to use rustdoc, I didn't know it also documents derived and macro-generated code.
How about `From<i32>` be implemented for enums?

So that this would work:

```rust
match phone_type.into() {
   PhoneType::Mobile => {},
  // etc.    
  _ => {}
}
```

Methods like `from_xxx` are often implemented as `From<Xxx>` in rust.

_EDIT: Just realised that `from_i32` returns an `Option`. `TryFrom<i32>` could work but isn't as ergonomic_

```rust
match phone_type.try_into().ok() {
   Some(PhoneType::Mobile) => {},
  // etc.    
  _ => {}
}
```

I see why this wasn't implemented this way - nevermind :)

Can someone please provide an example on how to do do the `rustdoc` trick? I'm scouring documentation, and I can't seem to find the right combination of arguments :disappointed: 

I was hoping that `cargo doc --open --document-private-items` would do the job, but seems like it's not the case.

(Although the comments above definitely helped!, so thank you for that!)
Hi @dvtomas, thanks for opening this issue, I agree the docs should be improved in this area.  The ergonomic helpers for enums were added after I wrote that bit in the readme, and I never went back and filled it in.

Toward your immediate issue, the best way to see what's available is to run `rustdoc` on the types and see the methods which they expose.  In the case of a `PhoneType` enum, it will expose a pair of methods which help convert from `i32`:

```rust
impl PhoneType {
  pub fn is_valid(value: i32) -> bool;
  pub fn from_i32(value: i32) -> Option<PhoneType>;
}
```

You can see a concrete example [here](https://docs.rs/prost-types/0.2.3/prost_types/field/enum.Cardinality.html).

As for the `Enumeration` trait, there is actually no such thing.  `derive(Enumeration)` is a trick which allows prost to generate these methods for enum types, but there's no corresponding trait.

I'm going to leave this issue open to track improving the enum docs.
Forgot to mention - there are other helper methods as well.  Wherever an Enumeration is used as a field in a Message, the message will have an 'accessor' methods to get/set the value as the proper type.  For instance, the [`Field`](https://docs.rs/prost-types/0.2.3/prost_types/struct.Field.html) struct contains a `Cardinality` field and the following methods:

```rust
impl Field {
  pub fn cardinality(&self) -> Cardinality;
  pub fn set_cardinality(&mut self, value: Cardinality);
}
```

Note that the first of these will return the default value (the first variant if otherwise unspecified) if the `i32` value is out of range.
Thank you for the info! It's a neat trick to use rustdoc, I didn't know it also documents derived and macro-generated code.
How about `From<i32>` be implemented for enums?

So that this would work:

```rust
match phone_type.into() {
   PhoneType::Mobile => {},
  // etc.    
  _ => {}
}
```

Methods like `from_xxx` are often implemented as `From<Xxx>` in rust.

_EDIT: Just realised that `from_i32` returns an `Option`. `TryFrom<i32>` could work but isn't as ergonomic_

```rust
match phone_type.try_into().ok() {
   Some(PhoneType::Mobile) => {},
  // etc.    
  _ => {}
}
```

I see why this wasn't implemented this way - nevermind :)

Can someone please provide an example on how to do do the `rustdoc` trick? I'm scouring documentation, and I can't seem to find the right combination of arguments :disappointed: 

I was hoping that `cargo doc --open --document-private-items` would do the job, but seems like it's not the case.

(Although the comments above definitely helped!, so thank you for that!)

Fix patch:
diff --git a/README.md b/README.md
index d5de8a649..049200332 100644
--- a/README.md
+++ b/README.md
@@ -107,10 +107,91 @@ Scalar value types are converted as follows:
 #### Enumerations
 
 All `.proto` enumeration types convert to the Rust `i32` type. Additionally,
-each enumeration type gets a corresponding Rust `enum` type, with helper methods
-to convert `i32` values to the enum type. The `enum` type isn't used directly as
-a field, because the Protobuf spec mandates that enumerations values are 'open',
-and decoding unrecognized enumeration values must be possible.
+each enumeration type gets a corresponding Rust `enum` type. For example, this
+`proto` enum:
+
+```proto
+enum PhoneType {
+  MOBILE = 0;
+  HOME = 1;
+  WORK = 2;
+}
+```
+
+gets this corresponding Rust enum [1]:
+
+```rust
+pub enum PhoneType {
+    Mobile = 0,
+    Home = 1,
+    Work = 2,
+}
+```
+
+You can convert a `PhoneType` value to an `i32` by doing:
+
+```rust
+PhoneType::Mobile as i32
+```
+
+The `#[derive(::prost::Enumeration)]` annotation added to the generated
+`PhoneType` adds these associated functions to the type:
+
+```rust
+impl PhoneType {
+    pub fn is_valid(value: i32) -> bool { ... }
+    pub fn from_i32(value: i32) -> Option<PhoneType> { ... }
+}
+```
+
+so you can convert an `i32` to its corresponding `PhoneType` value by doing,
+for example:
+
+```rust
+let phone_type = 2i32;
+
+match PhoneType::from_i32(phone_type) {
+    Some(PhoneType::Mobile) => ...,
+    Some(PhoneType::Home) => ...,
+    Some(PhoneType::Work) => ...,
+    None => ...,
+}
+```
+
+Additionally, wherever a `proto` enum is used as a field in a `Message`, the
+message will have 'accessor' methods to get/set the value of the field as the
+Rust enum type. For instance, this proto `PhoneNumber` message that has a field
+named `type` of type `PhoneType`:
+
+```proto
+message PhoneNumber {
+  string number = 1;
+  PhoneType type = 2;
+}
+```
+
+will become the following Rust type [1] with methods `type` and `set_type`:
+
+```rust
+pub struct PhoneNumber {
+    pub number: String,
+    pub r#type: i32, // the `r#` is needed because `type` is a Rust keyword
+}
+
+impl PhoneNumber {
+    pub fn r#type(&self) -> PhoneType { ... }
+    pub fn set_type(&mut self, value: PhoneType) { ... }
+}
+```
+
+Note that the getter methods will return the Rust enum's default value if the
+field has an invalid `i32` value.
+
+The `enum` type isn't used directly as a field, because the Protobuf spec
+mandates that enumerations values are 'open', and decoding unrecognized
+enumeration values must be possible.
+
+[1] Annotations have been elided for clarity. See below for a full example.
 
 #### Field Modifiers
 
@@ -215,27 +296,29 @@ message AddressBook {
 and the generated Rust code (`tutorial.rs`):
 
 ```rust
-#[derive(Clone, Debug, PartialEq, Message)]
+#[derive(Clone, PartialEq, ::prost::Message)]
 pub struct Person {
     #[prost(string, tag="1")]
-    pub name: String,
+    pub name: ::prost::alloc::string::String,
     /// Unique ID number for this person.
     #[prost(int32, tag="2")]
     pub id: i32,
     #[prost(string, tag="3")]
-    pub email: String,
+    pub email: ::prost::alloc::string::String,
     #[prost(message, repeated, tag="4")]
-    pub phones: Vec<person::PhoneNumber>,
+    pub phones: ::prost::alloc::vec::Vec<person::PhoneNumber>,
 }
+/// Nested message and enum types in `Person`.
 pub mod person {
-    #[derive(Clone, Debug, PartialEq, Message)]
+    #[derive(Clone, PartialEq, ::prost::Message)]
     pub struct PhoneNumber {
         #[prost(string, tag="1")]
-        pub number: String,
+        pub number: ::prost::alloc::string::String,
         #[prost(enumeration="PhoneType", tag="2")]
-        pub type_: i32,
+        pub r#type: i32,
     }
-    #[derive(Clone, Copy, Debug, PartialEq, Eq, Enumeration)]
+    #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)]
+    #[repr(i32)]
     pub enum PhoneType {
         Mobile = 0,
         Home = 1,
@@ -243,10 +326,10 @@ pub mod person {
     }
 }
 /// Our address book file is just one of these.
-#[derive(Clone, Debug, PartialEq, Message)]
+#[derive(Clone, PartialEq, ::prost::Message)]
 pub struct AddressBook {
     #[prost(message, repeated, tag="1")]
-    pub people: Vec<Person>,
+    pub people: ::prost::alloc::vec::Vec<Person>,
 }
 ```
 
diff --git a/prost-build/src/lib.rs b/prost-build/src/lib.rs
index 6353b7d0d..041e350e2 100644
--- a/prost-build/src/lib.rs
+++ b/prost-build/src/lib.rs
@@ -51,10 +51,10 @@
 //! `build.rs` build-script:
 //!
 //! ```rust,no_run
-//! # use std::io::Result;
+//! use std::io::Result;
 //! fn main() -> Result<()> {
-//!   prost_build::compile_protos(&["src/items.proto"], &["src/"])?;
-//!   Ok(())
+//!     prost_build::compile_protos(&["src/items.proto"], &["src/"])?;
+//!     Ok(())
 //! }
 //! ```
 //!


Test patch: