| <!-- WARNING: This file is machine generated by //src/tests/fidl/source_compatibility/gen, do not edit. --> |
| |
| Note: This document covers API impact only. For more details, see the |
| [ABI compatibility page](/docs/development/languages/fidl/guides/compatibility/README.md) |
| |
| # Add union member |
| |
| ## Overview |
| |
| -|[init](#init)|[step 1](#step-1)|[step 2](#step-2)|[step 3](#step-3) |
| ---|---|---|---|--- |
| fidl|[link](#fidl-init)||[link](#fidl-2)| |
| dart|[link](#dart-init)|[link](#dart-1)||[link](#dart-3) |
| go|[link](#go-init)|[link](#go-1)||[link](#go-3) |
| hlcpp|[link](#hlcpp-init)|[link](#hlcpp-1)||[link](#hlcpp-3) |
| llcpp|[link](#llcpp-init)|[link](#llcpp-1)||[link](#llcpp-3) |
| rust|[link](#rust-init)|[link](#rust-1)||[link](#rust-3) |
| |
| ## Initial State {#init} |
| |
| ### FIDL {#fidl-init} |
| |
| ```fidl |
| flexible union JsonValue { |
| 1: int32 int_value; |
| 2: string:MAX string_value; |
| }; |
| ``` |
| |
| ### Dart {#dart-init} |
| |
| ```dart |
| fidllib.JsonValue writer(String s) { |
| final asInt = int.tryParse(s); |
| if (asInt != null) { |
| return fidllib.JsonValue.withIntValue(asInt); |
| } |
| return fidllib.JsonValue.withStringValue(s); |
| } |
| |
| String reader(fidllib.JsonValue value) { |
| switch (value.$tag) { |
| case fidllib.JsonValueTag.intValue: |
| return '${value.intValue}'; |
| case fidllib.JsonValueTag.stringValue: |
| return value.stringValue; |
| default: |
| return '<${value.$unknownData.data.length} unknown bytes>'; |
| } |
| } |
| |
| ``` |
| |
| ### Go {#go-init} |
| |
| ```go |
| func writer(s string) lib.JsonValue { |
| n, err := strconv.ParseInt(s, 10, 32) |
| if err == nil { |
| return lib.JsonValueWithIntValue(int32(n)) |
| } |
| return lib.JsonValueWithStringValue(s) |
| } |
| |
| func reader(value lib.JsonValue) string { |
| switch value.Which() { |
| case lib.JsonValueIntValue: |
| return fmt.Sprintf("%d", value.IntValue) |
| case lib.JsonValueStringValue: |
| return value.StringValue |
| default: |
| return fmt.Sprintf("<%d unknown bytes>", len(value.GetUnknownData().Bytes)) |
| } |
| } |
| |
| ``` |
| |
| ### HLCPP {#hlcpp-init} |
| |
| ```cpp |
| fidl_test::JsonValue writer(const std::string& s) { |
| std::optional<int32_t> maybe_int = parse_as_int(s); |
| if (maybe_int) { |
| return fidl_test::JsonValue::WithIntValue(std::move(*maybe_int)); |
| } |
| auto val = s; |
| return fidl_test::JsonValue::WithStringValue(std::move(val)); |
| } |
| |
| std::string reader(const fidl_test::JsonValue& value) { |
| switch (value.Which()) { |
| case fidl_test::JsonValue::Tag::kIntValue: |
| return std::to_string(value.int_value()); |
| case fidl_test::JsonValue::Tag::kStringValue: |
| return value.string_value(); |
| case fidl_test::JsonValue::Tag::Invalid: |
| return "<uninitialized>"; |
| case fidl_test::JsonValue::Tag::kUnknown: { |
| std::ostringstream out; |
| out << "<" << value.UnknownBytes()->size() << " unknown bytes>"; |
| return out.str(); |
| } |
| } |
| } |
| ``` |
| |
| ### LLCPP {#llcpp-init} |
| |
| ```cpp |
| fidl_test::JsonValue writer(const std::string& s) { |
| std::optional<int32_t> maybe_int = parse_as_int(s); |
| if (maybe_int) { |
| return fidl_test::JsonValue::WithIntValue(std::make_unique<int32_t>(*maybe_int)); |
| } |
| return fidl_test::JsonValue::WithStringValue( |
| std::make_unique<fidl::StringView>(fidl::heap_copy_str(s))); |
| } |
| |
| std::string reader(const fidl_test::JsonValue& value) { |
| switch (value.which()) { |
| case fidl_test::JsonValue::Tag::kIntValue: |
| return std::to_string(value.int_value()); |
| case fidl_test::JsonValue::Tag::kStringValue: |
| return std::string(value.string_value().data(), value.string_value().size()); |
| case fidl_test::JsonValue::Tag::kUnknown: |
| return "<unknown>"; |
| } |
| } |
| ``` |
| |
| ### Rust {#rust-init} |
| |
| ```rust |
| fn writer(s: &str) -> fidl_lib::JsonValue { |
| let as_int = s.parse::<i32>(); |
| as_int |
| .map(|n| fidl_lib::JsonValue::IntValue(n)) |
| .unwrap_or(fidl_lib::JsonValue::StringValue(s.to_string())) |
| } |
| |
| fn reader(value: fidl_lib::JsonValue) -> String { |
| match value { |
| fidl_lib::JsonValue::IntValue(n) => format!("{}", n), |
| fidl_lib::JsonValue::StringValue(s) => s, |
| fidl_lib::JsonValueUnknown!() => "<unknown>".to_string(), |
| } |
| } |
| ``` |
| |
| ## Update Source Code {#step-1} |
| |
| ### Dart {#dart-1} |
| |
| - Evolve readers first by updating switch statements on the union tag to handle the soon-to-be-added variant as part of a default case. |
| |
| ```diff |
| if (asInt != null) { |
| return fidllib.JsonValue.withIntValue(asInt); |
| } |
| return fidllib.JsonValue.withStringValue(s); |
| } |
| |
| String reader(fidllib.JsonValue value) { |
| switch (value.$tag) { |
| case fidllib.JsonValueTag.intValue: |
| return '${value.intValue}'; |
| case fidllib.JsonValueTag.stringValue: |
| return value.stringValue; |
| + case fidllib.JsonValueTag.$unknown: |
| + return '<${value.$unknownData.data.length} unknown bytes>'; |
| default: |
| - return '<${value.$unknownData.data.length} unknown bytes>'; |
| + return '<unknown new member>'; |
| } |
| } |
| |
| |
| ``` |
| |
| ### Go {#go-1} |
| |
| - Evolve readers first by updating switch statements on the union tag to handle the soon-to-be-added variant as part of a default case. |
| |
| ```diff |
| if err == nil { |
| return lib.JsonValueWithIntValue(int32(n)) |
| } |
| return lib.JsonValueWithStringValue(s) |
| } |
| |
| func reader(value lib.JsonValue) string { |
| switch value.Which() { |
| case lib.JsonValueIntValue: |
| return fmt.Sprintf("%d", value.IntValue) |
| case lib.JsonValueStringValue: |
| return value.StringValue |
| + case lib.JsonValue_unknownData: |
| + return fmt.Sprintf("<%d unknown bytes>", len(value.GetUnknownData().Bytes)) |
| default: |
| - return fmt.Sprintf("<%d unknown bytes>", len(value.GetUnknownData().Bytes)) |
| + return "<unknown new member>" |
| } |
| } |
| |
| |
| ``` |
| |
| ### HLCPP {#hlcpp-1} |
| |
| - Evolve readers first by updating switch statements on the union tag to handle the soon-to-be-added variant as part of a default case. |
| |
| ```diff |
| switch (value.Which()) { |
| case fidl_test::JsonValue::Tag::kIntValue: |
| return std::to_string(value.int_value()); |
| case fidl_test::JsonValue::Tag::kStringValue: |
| return value.string_value(); |
| case fidl_test::JsonValue::Tag::Invalid: |
| return "<uninitialized>"; |
| case fidl_test::JsonValue::Tag::kUnknown: { |
| std::ostringstream out; |
| out << "<" << value.UnknownBytes()->size() << " unknown bytes>"; |
| return out.str(); |
| } |
| + default: |
| + return "<unknown new member>"; |
| } |
| } |
| |
| ``` |
| |
| ### LLCPP {#llcpp-1} |
| |
| - Evolve readers first by updating switch statements on the union tag to handle the soon-to-be-added variant as part of a default case. |
| |
| ```diff |
| } |
| return fidl_test::JsonValue::WithStringValue( |
| std::make_unique<fidl::StringView>(fidl::heap_copy_str(s))); |
| } |
| |
| std::string reader(const fidl_test::JsonValue& value) { |
| switch (value.which()) { |
| case fidl_test::JsonValue::Tag::kIntValue: |
| return std::to_string(value.int_value()); |
| case fidl_test::JsonValue::Tag::kStringValue: |
| return std::string(value.string_value().data(), value.string_value().size()); |
| case fidl_test::JsonValue::Tag::kUnknown: |
| + default: |
| return "<unknown>"; |
| } |
| } |
| |
| ``` |
| |
| ### Rust {#rust-1} |
| |
| - Evolve readers first by updating match statements to handle the soon-to-be-added variant as part of a catch-all case. |
| |
| ```diff |
| fn writer(s: &str) -> fidl_lib::JsonValue { |
| let as_int = s.parse::<i32>(); |
| as_int |
| .map(|n| fidl_lib::JsonValue::IntValue(n)) |
| .unwrap_or(fidl_lib::JsonValue::StringValue(s.to_string())) |
| } |
| |
| fn reader(value: fidl_lib::JsonValue) -> String { |
| match value { |
| fidl_lib::JsonValue::IntValue(n) => format!("{}", n), |
| fidl_lib::JsonValue::StringValue(s) => s, |
| - fidl_lib::JsonValueUnknown!() => "<unknown>".to_string(), |
| + _ => "<unknown>".to_string(), |
| } |
| } |
| |
| ``` |
| |
| ## Update FIDL Library {#step-2} |
| |
| - Add the new variant |
| |
| ```diff |
| flexible union JsonValue { |
| 1: int32 int_value; |
| 2: string:MAX string_value; |
| + 3: float32 float_value; |
| }; |
| |
| ``` |
| |
| ## Update Source Code {#step-3} |
| |
| ### Dart {#dart-3} |
| |
| - Writers can now start producing instances of the new variant. |
| - Readers should handle the new variant in switch statements. |
| |
| ```diff |
| fidllib.JsonValue writer(String s) { |
| + final asFloat = double.tryParse(s); |
| + if (asFloat != null) { |
| + return fidllib.JsonValue.withFloatValue(asFloat); |
| + } |
| final asInt = int.tryParse(s); |
| if (asInt != null) { |
| return fidllib.JsonValue.withIntValue(asInt); |
| } |
| return fidllib.JsonValue.withStringValue(s); |
| } |
| |
| String reader(fidllib.JsonValue value) { |
| switch (value.$tag) { |
| case fidllib.JsonValueTag.intValue: |
| return '${value.intValue}'; |
| case fidllib.JsonValueTag.stringValue: |
| return value.stringValue; |
| - case fidllib.JsonValueTag.$unknown: |
| + case fidllib.JsonValueTag.floatValue: |
| + return '${value.floatValue}'; |
| + default: |
| return '<${value.$unknownData.data.length} unknown bytes>'; |
| - default: |
| - return '<unknown new member>'; |
| } |
| } |
| |
| |
| ``` |
| |
| ### Go {#go-3} |
| |
| - Writers can now start producing instances of the new variant. |
| - Readers should handle the new variant in switch statements. |
| |
| ```diff |
| func writer(s string) lib.JsonValue { |
| n, err := strconv.ParseInt(s, 10, 32) |
| if err == nil { |
| return lib.JsonValueWithIntValue(int32(n)) |
| + } |
| + var f float64 |
| + f, err = strconv.ParseFloat(s, 64) |
| + if err == nil { |
| + return lib.JsonValueWithFloatValue(float32(f)) |
| } |
| return lib.JsonValueWithStringValue(s) |
| } |
| |
| func reader(value lib.JsonValue) string { |
| switch value.Which() { |
| case lib.JsonValueIntValue: |
| return fmt.Sprintf("%d", value.IntValue) |
| case lib.JsonValueStringValue: |
| return value.StringValue |
| - case lib.JsonValue_unknownData: |
| + case lib.JsonValueFloatValue: |
| + return fmt.Sprintf("%f", value.FloatValue) |
| + default: |
| return fmt.Sprintf("<%d unknown bytes>", len(value.GetUnknownData().Bytes)) |
| - default: |
| - return "<unknown new member>" |
| } |
| } |
| |
| |
| ``` |
| |
| ### HLCPP {#hlcpp-3} |
| |
| - Writers can now start producing instances of the new variant. |
| - Readers can replace the default case by handling the new variant directly. |
| |
| ```diff |
| fidl_test::JsonValue writer(const std::string& s) { |
| + std::optional<float> maybe_float = parse_as_float(s); |
| + if (maybe_float) { |
| + return fidl_test::JsonValue::WithFloatValue(std::move(*maybe_float)); |
| + } |
| + |
| std::optional<int32_t> maybe_int = parse_as_int(s); |
| if (maybe_int) { |
| return fidl_test::JsonValue::WithIntValue(std::move(*maybe_int)); |
| } |
| auto val = s; |
| return fidl_test::JsonValue::WithStringValue(std::move(val)); |
| } |
| |
| std::string reader(const fidl_test::JsonValue& value) { |
| switch (value.Which()) { |
| case fidl_test::JsonValue::Tag::kIntValue: |
| return std::to_string(value.int_value()); |
| case fidl_test::JsonValue::Tag::kStringValue: |
| return value.string_value(); |
| + case fidl_test::JsonValue::Tag::kFloatValue: |
| + return std::to_string(value.float_value()); |
| case fidl_test::JsonValue::Tag::Invalid: |
| return "<uninitialized>"; |
| case fidl_test::JsonValue::Tag::kUnknown: { |
| std::ostringstream out; |
| out << "<" << value.UnknownBytes()->size() << " unknown bytes>"; |
| return out.str(); |
| - } |
| - default: |
| - return "<unknown new member>"; |
| + }; |
| } |
| } |
| |
| ``` |
| |
| ### LLCPP {#llcpp-3} |
| |
| - Writers can now start producing instances of the new variant. |
| - Readers can replace the default case by handling the new variant directly. |
| |
| ```diff |
| fidl_test::JsonValue writer(const std::string& s) { |
| + std::optional<float> maybe_float = parse_as_float(s); |
| + ; |
| + if (maybe_float) { |
| + return fidl_test::JsonValue::WithIntValue(std::make_unique<int32_t>(*maybe_float)); |
| + } |
| std::optional<int32_t> maybe_int = parse_as_int(s); |
| if (maybe_int) { |
| return fidl_test::JsonValue::WithIntValue(std::make_unique<int32_t>(*maybe_int)); |
| } |
| return fidl_test::JsonValue::WithStringValue( |
| std::make_unique<fidl::StringView>(fidl::heap_copy_str(s))); |
| } |
| |
| std::string reader(const fidl_test::JsonValue& value) { |
| switch (value.which()) { |
| case fidl_test::JsonValue::Tag::kIntValue: |
| return std::to_string(value.int_value()); |
| case fidl_test::JsonValue::Tag::kStringValue: |
| return std::string(value.string_value().data(), value.string_value().size()); |
| + case fidl_test::JsonValue::Tag::kFloatValue: |
| + return std::to_string(value.float_value()); |
| case fidl_test::JsonValue::Tag::kUnknown: |
| - default: |
| return "<unknown>"; |
| } |
| } |
| |
| ``` |
| |
| ### Rust {#rust-3} |
| |
| - Writers can now start producing instances of the new variant. |
| - Readers can replace the default case by handling the new variant directly. |
| |
| ```diff |
| fn writer(s: &str) -> fidl_lib::JsonValue { |
| + let as_float = s.parse::<f32>(); |
| + if let Ok(val) = as_float { |
| + return fidl_lib::JsonValue::FloatValue(val); |
| + } |
| let as_int = s.parse::<i32>(); |
| as_int |
| .map(|n| fidl_lib::JsonValue::IntValue(n)) |
| .unwrap_or(fidl_lib::JsonValue::StringValue(s.to_string())) |
| } |
| |
| fn reader(value: fidl_lib::JsonValue) -> String { |
| match value { |
| fidl_lib::JsonValue::IntValue(n) => format!("{}", n), |
| fidl_lib::JsonValue::StringValue(s) => s, |
| - _ => "<unknown>".to_string(), |
| + fidl_lib::JsonValue::FloatValue(v) => format!("{:.2}", v), |
| + fidl_lib::JsonValueUnknown!() => "<unknown>".to_string(), |
| } |
| } |
| |
| ``` |
| |