Note: This document covers API impact only. For more details, see the ABI compatibility page

Change an enum from strict to flexible

Overview

- init step 1 step 2 step 3 step 4
fidl link link link
dart link link
go link link
hlcpp link link link
llcpp link link link
rust link link link

Initial State {#init}

FIDL {#fidl-init}

  1. strict enum Color : int32 {
  2. RED = 1;
  3. BLUE = 2;
  4. UNKNOWN_COLOR = 3;
  5. };

Dart {#dart-init}

  1. fidllib.Color writer(String s) {
  2. if (s == 'red') {
  3. return fidllib.Color.red;
  4. } else if (s == 'blue') {
  5. return fidllib.Color.blue;
  6. } else {
  7. return fidllib.Color.unknownColor;
  8. }
  9. }
  10. String reader(fidllib.Color color) {
  11. switch (color) {
  12. case fidllib.Color.blue:
  13. return 'blue';
  14. case fidllib.Color.red:
  15. return 'red';
  16. case fidllib.Color.unknownColor:
  17. return 'unknown';
  18. default:
  19. return 'error';
  20. }
  21. }

Go {#go-init}

  1. func writer(s string) lib.Color {
  2. switch {
  3. case s == "blue":
  4. return lib.ColorBlue
  5. case s == "red":
  6. return lib.ColorRed
  7. default:
  8. return lib.ColorUnknownColor
  9. }
  10. }
  11. func reader(color lib.Color) (string, error) {
  12. switch color {
  13. case lib.ColorBlue:
  14. return "blue", nil
  15. case lib.ColorRed:
  16. return "red", nil
  17. case lib.ColorUnknownColor:
  18. return "unknown", nil
  19. default:
  20. return "", errors.New("invalid color enum")
  21. }
  22. }

HLCPP {#hlcpp-init}

  1. template <fidl_test::Color color>
  2. class ComplementaryColors {};
  3. fidl_test::Color writer(std::string s) {
  4. if (s == "red") {
  5. return fidl_test::Color::RED;
  6. } else if (s == "blue") {
  7. return fidl_test::Color::BLUE;
  8. } else {
  9. return fidl_test::Color::UNKNOWN_COLOR;
  10. }
  11. }
  12. std::string reader(fidl_test::Color color) {
  13. switch (color) {
  14. case fidl_test::Color::RED:
  15. return "red";
  16. case fidl_test::Color::BLUE:
  17. return "blue";
  18. case fidl_test::Color::UNKNOWN_COLOR:
  19. return "unknown";
  20. default:
  21. return "error";
  22. }
  23. }

LLCPP {#llcpp-init}

  1. template <fidl_test::Color color>
  2. class ComplementaryColors {};
  3. fidl_test::Color writer(std::string s) {
  4. if (s == "red") {
  5. return fidl_test::Color::RED;
  6. } else if (s == "blue") {
  7. return fidl_test::Color::BLUE;
  8. } else {
  9. return fidl_test::Color::UNKNOWN_COLOR;
  10. }
  11. }
  12. std::string reader(fidl_test::Color color) {
  13. switch (color) {
  14. case fidl_test::Color::RED:
  15. return "red";
  16. case fidl_test::Color::BLUE:
  17. return "blue";
  18. case fidl_test::Color::UNKNOWN_COLOR:
  19. return "unknown";
  20. default:
  21. return "error";
  22. }
  23. }

Rust {#rust-init}

  1. fn writer(s: &str) -> fidl_lib::Color {
  2. match s {
  3. "red" => fidl_lib::Color::Red,
  4. "blue" => fidl_lib::Color::Blue,
  5. _ => fidl_lib::Color::UnknownColor,
  6. }
  7. }
  8. fn reader(color: fidl_lib::Color) -> &'static str {
  9. match color {
  10. fidl_lib::Color::Red => "red",
  11. fidl_lib::Color::Blue => "blue",
  12. fidl_lib::Color::UnknownColor => "unknown",
  13. }
  14. }

Update Source Code {#step-1}

HLCPP {#hlcpp-1}

  • Remove any usages of the enum as a non-type template parameter. These usages are not supported for flexible enums.
  1. - template <fidl_test::Color color>
  2. - class ComplementaryColors {};
  3. -
  4. fidl_test::Color writer(std::string s) {
  5. if (s == "red") {
  6. return fidl_test::Color::RED;
  7. } else if (s == "blue") {
  8. return fidl_test::Color::BLUE;
  9. } else {
  10. return fidl_test::Color::UNKNOWN_COLOR;
  11. }
  12. }
  13. std::string reader(fidl_test::Color color) {
  14. switch (color) {

LLCPP {#llcpp-1}

  • Remove any usages of the enum as a non-type template parameter. These usages are not supported for flexible enums.
  1. - template <fidl_test::Color color>
  2. - class ComplementaryColors {};
  3. -
  4. fidl_test::Color writer(std::string s) {
  5. if (s == "red") {
  6. return fidl_test::Color::RED;
  7. } else if (s == "blue") {
  8. return fidl_test::Color::BLUE;
  9. } else {
  10. return fidl_test::Color::UNKNOWN_COLOR;
  11. }
  12. }
  13. std::string reader(fidl_test::Color color) {
  14. switch (color) {

Rust {#rust-1}

  • Allow unreachable patterns and add an underscore arm to any match statements on the enum.
  1. fn writer(s: &str) -> fidl_lib::Color {
  2. match s {
  3. "red" => fidl_lib::Color::Red,
  4. "blue" => fidl_lib::Color::Blue,
  5. _ => fidl_lib::Color::UnknownColor,
  6. }
  7. }
  8. fn reader(color: fidl_lib::Color) -> &'static str {
  9. + #[allow(unreachable_patterns)]
  10. match color {
  11. fidl_lib::Color::Red => "red",
  12. fidl_lib::Color::Blue => "blue",
  13. - fidl_lib::Color::UnknownColor => "unknown",
  14. + _ => "unknown",
  15. }
  16. }

Update FIDL Library {#step-2}

  • Change from strict to flexible
  • If the enum had a member representing an unknown enum, add the [Unknown] attribute to it
  1. - strict enum Color : int32 {
  2. + flexible enum Color : int32 {
  3. RED = 1;
  4. BLUE = 2;
  5. + [Unknown]
  6. UNKNOWN_COLOR = 3;
  7. };

Update Source Code {#step-3}

Dart {#dart-3}

  • If using a custom unknown with the [Unknown] attribute, update readers and writers to use isUnknown and $unknown.
  1. fidllib.Color writer(String s) {
  2. if (s == 'red') {
  3. return fidllib.Color.red;
  4. } else if (s == 'blue') {
  5. return fidllib.Color.blue;
  6. } else {
  7. - return fidllib.Color.unknownColor;
  8. + return fidllib.Color.$unknown;
  9. }
  10. }
  11. String reader(fidllib.Color color) {
  12. + if (color.isUnknown()) {
  13. + return 'unknown';
  14. + }
  15. switch (color) {
  16. case fidllib.Color.blue:
  17. return 'blue';
  18. case fidllib.Color.red:
  19. return 'red';
  20. - case fidllib.Color.unknownColor:
  21. - return 'unknown';
  22. default:
  23. return 'error';
  24. }
  25. }

Go {#go-3}

  • If using a custom unknown with the [Unknown] attribute, update readers and writers to use IsUnknown and the _Unknown constant.
  • You can now use any flexible enum specific APIs
  1. func writer(s string) lib.Color {
  2. switch {
  3. case s == "blue":
  4. return lib.ColorBlue
  5. case s == "red":
  6. return lib.ColorRed
  7. default:
  8. - return lib.ColorUnknownColor
  9. + return lib.Color_Unknown
  10. }
  11. }
  12. func reader(color lib.Color) (string, error) {
  13. + if color.IsUnknown() {
  14. + return "unknown", nil
  15. + }
  16. switch color {
  17. case lib.ColorBlue:
  18. return "blue", nil
  19. case lib.ColorRed:
  20. return "red", nil
  21. - case lib.ColorUnknownColor:
  22. - return "unknown", nil
  23. default:
  24. return "", errors.New("invalid color enum")
  25. }
  26. }

HLCPP {#hlcpp-3}

  • If using a custom unknown with the [Unknown] attribute, update readers and writers to use IsUnknown and Unknown.
  • You can now use any flexible enum specific APIs
  1. fidl_test::Color writer(std::string s) {
  2. if (s == "red") {
  3. return fidl_test::Color::RED;
  4. } else if (s == "blue") {
  5. return fidl_test::Color::BLUE;
  6. } else {
  7. - return fidl_test::Color::UNKNOWN_COLOR;
  8. + return fidl_test::Color::Unknown();
  9. }
  10. }
  11. std::string reader(fidl_test::Color color) {
  12. + if (color.IsUnknown()) {
  13. + return "unknown";
  14. + }
  15. switch (color) {
  16. case fidl_test::Color::RED:
  17. return "red";
  18. case fidl_test::Color::BLUE:
  19. return "blue";
  20. - case fidl_test::Color::UNKNOWN_COLOR:
  21. - return "unknown";
  22. default:
  23. return "error";
  24. }
  25. }

LLCPP {#llcpp-3}

  • If using a custom unknown with the [Unknown] attribute, update readers and writers to use IsUnknown and Unknown.
  • You can now use any flexible enum specific APIs
  1. fidl_test::Color writer(std::string s) {
  2. if (s == "red") {
  3. return fidl_test::Color::RED;
  4. } else if (s == "blue") {
  5. return fidl_test::Color::BLUE;
  6. } else {
  7. - return fidl_test::Color::UNKNOWN_COLOR;
  8. + return fidl_test::Color::Unknown();
  9. }
  10. }
  11. std::string reader(fidl_test::Color color) {
  12. + if (color.IsUnknown()) {
  13. + return "unknown";
  14. + }
  15. switch (color) {
  16. case fidl_test::Color::RED:
  17. return "red";
  18. case fidl_test::Color::BLUE:
  19. return "blue";
  20. - case fidl_test::Color::UNKNOWN_COLOR:
  21. - return "unknown";
  22. default:
  23. return "error";
  24. }
  25. }

Rust {#rust-3}

  • If using a custom unknown with the [Unknown] attribute, update readers and writers to use the ColorUnknown! macro (or is_unknown outside of match statements) and unknown.
  • You can now use any flexible enum specific APIs
  1. fn writer(s: &str) -> fidl_lib::Color {
  2. match s {
  3. "red" => fidl_lib::Color::Red,
  4. "blue" => fidl_lib::Color::Blue,
  5. - _ => fidl_lib::Color::UnknownColor,
  6. + _ => fidl_lib::Color::unknown(),
  7. }
  8. }
  9. fn reader(color: fidl_lib::Color) -> &'static str {
  10. - #[allow(unreachable_patterns)]
  11. match color {
  12. fidl_lib::Color::Red => "red",
  13. fidl_lib::Color::Blue => "blue",
  14. - _ => "unknown",
  15. + fidl_lib::ColorUnknown!() => "unknown",
  16. }
  17. }

Update FIDL Library {#step-4}

  • If transitioning away from a custom unknown member, you can now remove the placeholder member at this point.
  1. flexible enum Color : int32 {
  2. RED = 1;
  3. BLUE = 2;
  4. - [Unknown]
  5. - UNKNOWN_COLOR = 3;
  6. };