tree: 4819bf83e4cf4eef5503cb5a5951f28c5a593978 [path history] [tgz]
  1. dart/
  2. fidl/
  3. go/
  4. hlcpp/
  5. llcpp/
  6. rust/
  7. BUILD.gn
  8. README.md
  9. test.json
  10. test_gn_sidecar.json
src/tests/fidl/source_compatibility/union-flexible-strict/README.md

Change a union from flexible to strict

Overview

-initstep 1step 2step 3
fidllinklink
dartlinklinklink
golinklink
hlcpplinklinklink
llcpplinklinklink
rustlinklinklink

Initial State

FIDL

flexible union JsonValue {
    1: int32 int_value;
    2: string:MAX string_value;
};

Dart

void useUnion(fidllib.JsonValue value) {
  switch (value.$tag) {
    case fidllib.JsonValueTag.intValue:
      print('int value: ${value.intValue}');
      break;
    case fidllib.JsonValueTag.stringValue:
      print('string value: ${value.stringValue}');
      break;
    case fidllib.JsonValueTag.$unknown:
      print('unknown variant: ${value.$unknownData}');
      break;
  }
}

Go

func useUnion(value lib.JsonValue) {
	switch value.Which() {
	case lib.JsonValueIntValue:
		fmt.Printf("int value: %d\n", value.IntValue)
	case lib.JsonValueStringValue:
		fmt.Printf("string value: %s\n", value.StringValue)
	case lib.JsonValue_unknownData:
		fmt.Printf("unknown data: %+v\n", value.GetUnknownData())
	default:
		fmt.Println("<unknown tag>")
	}
}

HLCPP

void use_union(fidl_test::JsonValue value) {
  switch (value.Which()) {
    case fidl_test::JsonValue::Tag::kIntValue:
      printf("int value: %d\n", value.int_value());
      break;
    case fidl_test::JsonValue::Tag::kStringValue:
      printf("string value: %s\n", value.string_value().c_str());
      break;
    case fidl_test::JsonValue::Tag::Invalid:
      printf("<uninitialized union>\n");
      break;
    case fidl_test::JsonValue::Tag::kUnknown:
      printf("<%lu unknown bytes>\n", value.UnknownBytes()->size());
      break;
  }
}

LLCPP

void use_union(fidl_test::JsonValue* value) {
  switch (value->which()) {
    case fidl_test::JsonValue::Tag::kIntValue:
      printf("int value: %d\n", value->int_value());
      break;
    case fidl_test::JsonValue::Tag::kStringValue:
      printf("string value: %s\n", value->string_value().data());
      break;
    case fidl_test::JsonValue::Tag::kUnknown:
      printf("<unknown data>\n");
      break;
  }
}

Rust

fn use_union(value: &fidl_lib::JsonValue) {
    match value {
        fidl_lib::JsonValue::IntValue(n) => println!("int value: {}", n),
        fidl_lib::JsonValue::StringValue(s) => println!("string: {}", s),
        fidl_lib::JsonValueUnknown!() => println!("<unknown union>"),
    };
}

Update Source Code

Dart

  • Replace the unknown tag with a default case in any switch statements
  void useUnion(fidllib.JsonValue value) {
    switch (value.$tag) {
      case fidllib.JsonValueTag.intValue:
        print('int value: ${value.intValue}');
        break;
      case fidllib.JsonValueTag.stringValue:
        print('string value: ${value.stringValue}');
        break;
-     case fidllib.JsonValueTag.$unknown:
+     default:
+       // Note: unknown variants will fail to decode until the union is marked flexible
        print('unknown variant: ${value.$unknownData}');
        break;
    }
  }
  

Go

  • Remove usages of any flexible union specific APIs
  func useUnion(value lib.JsonValue) {
  	switch value.Which() {
  	case lib.JsonValueIntValue:
  		fmt.Printf("int value: %d\n", value.IntValue)
  	case lib.JsonValueStringValue:
  		fmt.Printf("string value: %s\n", value.StringValue)
- 	case lib.JsonValue_unknownData:
- 		fmt.Printf("unknown data: %+v\n", value.GetUnknownData())
  	default:
  		fmt.Println("<unknown tag>")
  	}
  }
  

HLCPP

  • Replace the kUnknown tag with a default case in any switch statements
  • Remove usages of any flexible union specific APIs
  void use_union(fidl_test::JsonValue value) {
    switch (value.Which()) {
      case fidl_test::JsonValue::Tag::kIntValue:
        printf("int value: %d\n", value.int_value());
        break;
      case fidl_test::JsonValue::Tag::kStringValue:
        printf("string value: %s\n", value.string_value().c_str());
        break;
      case fidl_test::JsonValue::Tag::Invalid:
        printf("<uninitialized union>\n");
        break;
-     case fidl_test::JsonValue::Tag::kUnknown:
-       printf("<%lu unknown bytes>\n", value.UnknownBytes()->size());
-       break;
+     default:
+       printf("<unknown variant>\n");
    }
  }
  

LLCPP

  • Replace the kUnknown tag with a default case in any switch statements
  • Remove usages of any flexible union specific APIs
  void use_union(fidl_test::JsonValue* value) {
    switch (value->which()) {
      case fidl_test::JsonValue::Tag::kIntValue:
        printf("int value: %d\n", value->int_value());
        break;
      case fidl_test::JsonValue::Tag::kStringValue:
        printf("string value: %s\n", value->string_value().data());
        break;
-     case fidl_test::JsonValue::Tag::kUnknown:
-       printf("<unknown data>\n");
-       break;
+     default:
+       printf("<unknown variant>\n");
    }
  }

Rust

  • Add [allow(unreachable_patterns)] and an underscore arm to match statements on the union
  fn use_union(value: &fidl_lib::JsonValue) {
+     #[allow(unreachable_patterns)]
      match value {
          fidl_lib::JsonValue::IntValue(n) => println!("int value: {}", n),
          fidl_lib::JsonValue::StringValue(s) => println!("string: {}", s),
-         fidl_lib::JsonValueUnknown!() => println!("<unknown union>"),
+         _ => {}
      };
  }

Update FIDL Library

  • Change the union from flexible to strict
- flexible union JsonValue {
+ strict union JsonValue {
      1: int32 int_value;
      2: string:MAX string_value;
  };

Update Source Code

Dart

  • You can now remove the default case in any switch statements
  void useUnion(fidllib.JsonValue value) {
+   assert(value.$unknownData == null);
    switch (value.$tag) {
      case fidllib.JsonValueTag.intValue:
        print('int value: ${value.intValue}');
        break;
      case fidllib.JsonValueTag.stringValue:
        print('string value: ${value.stringValue}');
        break;
-     default:
-       // Note: unknown variants will fail to decode until the union is marked flexible
-       print('unknown variant: ${value.$unknownData}');
-       break;
    }
  }
  

HLCPP

  • You can now remove the default case
  void use_union(fidl_test::JsonValue value) {
    switch (value.Which()) {
      case fidl_test::JsonValue::Tag::kIntValue:
        printf("int value: %d\n", value.int_value());
        break;
      case fidl_test::JsonValue::Tag::kStringValue:
        printf("string value: %s\n", value.string_value().c_str());
        break;
      case fidl_test::JsonValue::Tag::Invalid:
        printf("<uninitialized union>\n");
        break;
-     default:
-       printf("<unknown variant>\n");
    }
  }
  

LLCPP

  • You can now remove the default case
  void use_union(fidl_test::JsonValue* value) {
    switch (value->which()) {
      case fidl_test::JsonValue::Tag::kIntValue:
        printf("int value: %d\n", value->int_value());
        break;
      case fidl_test::JsonValue::Tag::kStringValue:
        printf("string value: %s\n", value->string_value().data());
        break;
-     default:
-       printf("<unknown variant>\n");
    }
  }

Rust

  • Remove the attribute and underscore arm
  fn use_union(value: &fidl_lib::JsonValue) {
-     #[allow(unreachable_patterns)]
      match value {
          fidl_lib::JsonValue::IntValue(n) => println!("int value: {}", n),
          fidl_lib::JsonValue::StringValue(s) => println!("string: {}", s),
-         _ => {}
      };
  }