Skip to content

Latest commit

 

History

History
439 lines (362 loc) · 9.78 KB

File metadata and controls

439 lines (362 loc) · 9.78 KB

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}

type Color = strict enum : int32 {
    RED = 1;
    BLUE = 2;
    UNKNOWN_COLOR = 3;
};

Dart {#dart-init}

fidllib.Color writer(String s) {
  if (s == 'red') {
    return fidllib.Color.red;
  } else if (s == 'blue') {
    return fidllib.Color.blue;
  } else {
    return fidllib.Color.unknownColor;
  }
}

String reader(fidllib.Color color) {
  switch (color) {
    case fidllib.Color.blue:
      return 'blue';
    case fidllib.Color.red:
      return 'red';
    case fidllib.Color.unknownColor:
      return 'unknown';
    default:
      return 'error';
  }
}

Go {#go-init}

func writer(s string) lib.Color {
	switch {
	case s == "blue":
		return lib.ColorBlue
	case s == "red":
		return lib.ColorRed
	default:
		return lib.ColorUnknownColor
	}
}

func reader(color lib.Color) (string, error) {
	switch color {
	case lib.ColorBlue:
		return "blue", nil
	case lib.ColorRed:
		return "red", nil
	case lib.ColorUnknownColor:
		return "unknown", nil
	default:
		return "", errors.New("invalid color enum")
	}
}

HLCPP {#hlcpp-init}

template <fidl_test::Color color>
class ComplementaryColors {};

fidl_test::Color writer(std::string s) {
  if (s == "red") {
    return fidl_test::Color::RED;
  } else if (s == "blue") {
    return fidl_test::Color::BLUE;
  } else {
    return fidl_test::Color::UNKNOWN_COLOR;
  }
}

std::string reader(fidl_test::Color color) {
  switch (color) {
    case fidl_test::Color::RED:
      return "red";
    case fidl_test::Color::BLUE:
      return "blue";
    case fidl_test::Color::UNKNOWN_COLOR:
      return "unknown";
    default:
      return "error";
  }
}

LLCPP {#llcpp-init}

template <fidl_test::wire::Color color>
class ComplementaryColors {};

fidl_test::wire::Color writer(std::string s) {
  if (s == "red") {
    return fidl_test::wire::Color::kRed;
  } else if (s == "blue") {
    return fidl_test::wire::Color::kBlue;
  } else {
    return fidl_test::wire::Color::kUnknownColor;
  }
}

std::string reader(fidl_test::wire::Color color) {
  switch (color) {
    case fidl_test::wire::Color::kRed:
      return "red";
    case fidl_test::wire::Color::kBlue:
      return "blue";
    case fidl_test::wire::Color::kUnknownColor:
      return "unknown";
    default:
      return "error";
  }
}

Rust {#rust-init}

fn writer(s: &str) -> fidl_lib::Color {
    match s {
        "red" => fidl_lib::Color::Red,
        "blue" => fidl_lib::Color::Blue,
        _ => fidl_lib::Color::UnknownColor,
    }
}

fn reader(color: fidl_lib::Color) -> &'static str {
    match color {
        fidl_lib::Color::Red => "red",
        fidl_lib::Color::Blue => "blue",
        fidl_lib::Color::UnknownColor => "unknown",
    }
}

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.
- template <fidl_test::Color color>
- class ComplementaryColors {};
- 
  fidl_test::Color writer(std::string s) {
    if (s == "red") {
      return fidl_test::Color::RED;
    } else if (s == "blue") {
      return fidl_test::Color::BLUE;
    } else {
      return fidl_test::Color::UNKNOWN_COLOR;
    }
  }
  
  std::string reader(fidl_test::Color color) {
    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.
- template <fidl_test::wire::Color color>
- class ComplementaryColors {};
- 
  fidl_test::wire::Color writer(std::string s) {
    if (s == "red") {
      return fidl_test::wire::Color::kRed;
    } else if (s == "blue") {
      return fidl_test::wire::Color::kBlue;
    } else {
      return fidl_test::wire::Color::kUnknownColor;
    }
  }
  
  std::string reader(fidl_test::wire::Color color) {
    switch (color) {

Rust {#rust-1}

  • Allow unreachable patterns and add an underscore arm to any match statements on the enum.
  fn writer(s: &str) -> fidl_lib::Color {
      match s {
          "red" => fidl_lib::Color::Red,
          "blue" => fidl_lib::Color::Blue,
          _ => fidl_lib::Color::UnknownColor,
      }
  }
  
  fn reader(color: fidl_lib::Color) -> &'static str {
+     #[allow(unreachable_patterns)]
      match color {
          fidl_lib::Color::Red => "red",
          fidl_lib::Color::Blue => "blue",
-         fidl_lib::Color::UnknownColor => "unknown",
+         _ => "unknown",
      }
  }

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
- type Color = strict enum : int32 {
+ type Color = flexible enum : int32 {
      RED = 1;
      BLUE = 2;
+     @unknown
      UNKNOWN_COLOR = 3;
  };

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.
  fidllib.Color writer(String s) {
    if (s == 'red') {
      return fidllib.Color.red;
    } else if (s == 'blue') {
      return fidllib.Color.blue;
    } else {
-     return fidllib.Color.unknownColor;
+     return fidllib.Color.$unknown;
    }
  }
  
  String reader(fidllib.Color color) {
+   if (color.isUnknown()) {
+     return 'unknown';
+   }
    switch (color) {
      case fidllib.Color.blue:
        return 'blue';
      case fidllib.Color.red:
        return 'red';
-     case fidllib.Color.unknownColor:
-       return 'unknown';
      default:
        return 'error';
    }
  }

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
  func writer(s string) lib.Color {
  	switch {
  	case s == "blue":
  		return lib.ColorBlue
  	case s == "red":
  		return lib.ColorRed
  	default:
- 		return lib.ColorUnknownColor
+ 		return lib.Color_Unknown
  	}
  }
  
  func reader(color lib.Color) (string, error) {
+ 	if color.IsUnknown() {
+ 		return "unknown", nil
+ 	}
  	switch color {
  	case lib.ColorBlue:
  		return "blue", nil
  	case lib.ColorRed:
  		return "red", nil
- 	case lib.ColorUnknownColor:
- 		return "unknown", nil
  	default:
  		return "", errors.New("invalid color enum")
  	}
  }
  

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
  fidl_test::Color writer(std::string s) {
    if (s == "red") {
      return fidl_test::Color::RED;
    } else if (s == "blue") {
      return fidl_test::Color::BLUE;
    } else {
-     return fidl_test::Color::UNKNOWN_COLOR;
+     return fidl_test::Color::Unknown();
    }
  }
  
  std::string reader(fidl_test::Color color) {
+   if (color.IsUnknown()) {
+     return "unknown";
+   }
    switch (color) {
      case fidl_test::Color::RED:
        return "red";
      case fidl_test::Color::BLUE:
        return "blue";
-     case fidl_test::Color::UNKNOWN_COLOR:
-       return "unknown";
      default:
        return "error";
    }
  }

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
  fidl_test::wire::Color writer(std::string s) {
    if (s == "red") {
      return fidl_test::wire::Color::kRed;
    } else if (s == "blue") {
      return fidl_test::wire::Color::kBlue;
    } else {
-     return fidl_test::wire::Color::kUnknownColor;
+     return fidl_test::wire::Color::Unknown();
    }
  }
  
  std::string reader(fidl_test::wire::Color color) {
+   if (color.IsUnknown()) {
+     return "unknown";
+   }
    switch (color) {
      case fidl_test::wire::Color::kRed:
        return "red";
      case fidl_test::wire::Color::kBlue:
        return "blue";
-     case fidl_test::wire::Color::kUnknownColor:
-       return "unknown";
      default:
        return "error";
    }
  }

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
  fn writer(s: &str) -> fidl_lib::Color {
      match s {
          "red" => fidl_lib::Color::Red,
          "blue" => fidl_lib::Color::Blue,
-         _ => fidl_lib::Color::UnknownColor,
+         _ => fidl_lib::Color::unknown(),
      }
  }
  
  fn reader(color: fidl_lib::Color) -> &'static str {
-     #[allow(unreachable_patterns)]
      match color {
          fidl_lib::Color::Red => "red",
          fidl_lib::Color::Blue => "blue",
-         _ => "unknown",
+         fidl_lib::ColorUnknown!() => "unknown",
      }
  }

Update FIDL Library {#step-4}

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