[fidl][doc] Guidance on enums

Change-Id: I4e376e56dc85d5b95b72bc6e0bee500c626986b6
diff --git a/docs/development/api/fidl.md b/docs/development/api/fidl.md
index 0076a3a..51c2b04 100644
--- a/docs/development/api/fidl.md
+++ b/docs/development/api/fidl.md
@@ -625,7 +625,7 @@
 you're unsure, use 32-bit values for small quantities and 64-bit values for
 large ones.
 
-### Errors
+### How should I represent errors?
 
 Select the appropriate error type for your use case and be consistent about how
 you report errors.
@@ -639,16 +639,74 @@
 enum when you expect clients to receive the error and then stop rather than
 propagate the error to another system.
 
-If a method can return either an error or a result, use the following pattern:
+There are two patterns for methods that can return a result or an error:
+
+ * Prefer using the `error` syntax to clearly document and convey a
+   possible erroneous return, and take advantage of tailored target language
+   bindings;
+
+ * Use the
+   [optional value with error enum](#using-optional-value-with-error-enum)
+   for cases when you need maximal performance.
+
+The performance difference between the [error syntax](#using-the-error-syntax)
+vs [optional value with error enum](#using-optional-value-with-error-enum) are
+small:
+
+  * Slightly bigger payload (8 extra bytes for values, 16 extra bytes for
+    errors);
+  * Since the value and error will be in an envelope, there is additional work
+    to record/verify the number of bytes and number of handles;
+  * Both will represent the value out-of-line, and therefore require a pointer
+    indirection.
+
+### Using the error syntax
+
+Methods can take an optional `error <type>` specifier to indicate that they
+return a value, or error out and produce `<type>`. Here is an example:
 
 ```fidl
-enum MyStatus { OK; FOO; BAR; ... };
+// Only erroneous status are listed
+enum MyErrorCode {
+    ERR_MISSING_FOO = 1;  // avoid using 0
+    ERR_NO_BAR = 2;
+    ...
+};
 
 protocol Frobinator {
-    1: Frobinate(...) -> (MyStatus status, FrobinateResult? result);
+    1: Frobinate(...) -> (FrobinateResult value) error MyErrorCode;
 };
 ```
 
+When using this pattern, you can either use an `int32`, `uint32`, or an enum
+thereof to represent the kind of error returned. In most cases, returning an
+enum is the preferred approach. As noted in the [enum](#enum) section, it is best
+to avoid using the value `0`.
+
+#### Using optional value with error enum
+
+When maximal performance is required, defining a method with two returns, an
+optional value and an error code, is common practice. See for instance:
+
+```fidl
+enum MyErrorCode {
+    OK = 0;               // The success value should be 0,
+    ERR_MISSING_FOO = 1;  // with erroneous status next.
+    ERR_NO_BAR = 2;
+    ...
+};
+
+protocol Frobinator {
+    1: Frobinate(...) -> (FrobinateResult? value, MyErrorCode err);
+};
+```
+
+When using this pattern, returning an enum is the preferred approach. Here,
+defining the `0` value as the "success" is best. For further details, refer
+to the [enum](#enum) section.
+
+#### Avoid messages and descriptions in errors
+
 In some unusual situations, protocols may include a string description of the
 error in addition to a `status` or enum value if the range of possible error
 conditions is large and descriptive error messages are likely to be useful to
@@ -832,6 +890,21 @@
 to represent a MIME type because MIME types are controlled (at least in theory)
 by an IANA registry.
 
+We recommend that, where possible, developers avoid use of `0` as an enum value.
+Because many target languages use `0` as the default value for integers, it can
+be difficult for to distinguish whether a `0` value was set intentionally, or
+instead was set because it is the default. For instance, the
+`fuchsia.module.StoryState` defines three values:  `RUNNING` with value `1`,
+`STOPPING` with value `2`, and `STOPPED` with value `3`.
+
+There are two cases where using the value `0` is appropriate:
+
+  * The enum has a natural default, initial, or unknown state;
+
+  * The enum defines an error code used in the
+    [optional value with error enum](#using-optional-value-with-error-enum)
+    pattern.
+
 #### bits
 
 If your protocol has a bitfield, represent its values using `bits` values