text: // Copyright 2013 The Flutter Authors. All rights reserved.
  // Use of this source code is governed by a BSD-style license that can be
  // found in the LICENSE file.
  
  #include "flutter/shell/platform/linux/public/flutter_linux/fl_method_response.h"
  
  #include <gmodule.h>
  
  G_DEFINE_QUARK(fl_method_response_error_quark, fl_method_response_error)
  
  struct _FlMethodSuccessResponse {
    FlMethodResponse parent_instance;
  
    FlValue* result;
  };
  
  struct _FlMethodErrorResponse {
    FlMethodResponse parent_instance;
  
    gchar* code;
    gchar* message;
    FlValue* details;
  };
  
  struct _FlMethodNotImplementedResponse {
    FlMethodResponse parent_instance;
  };
  
  // Added here to stop the compiler from optimising this function away.
  G_MODULE_EXPORT GType fl_method_response_get_type();
  
  G_DEFINE_TYPE(FlMethodResponse, fl_method_response, G_TYPE_OBJECT)
  G_DEFINE_TYPE(FlMethodSuccessResponse,
                fl_method_success_response,
                fl_method_response_get_type())
  G_DEFINE_TYPE(FlMethodErrorResponse,
                fl_method_error_response,
                fl_method_response_get_type())
  G_DEFINE_TYPE(FlMethodNotImplementedResponse,
                fl_method_not_implemented_response,
                fl_method_response_get_type())
  
  static void fl_method_response_class_init(FlMethodResponseClass* klass) {}
  
  static void fl_method_response_init(FlMethodResponse* self) {}
  
  static void fl_method_success_response_dispose(GObject* object) {
    FlMethodSuccessResponse* self = FL_METHOD_SUCCESS_RESPONSE(object);
  
    g_clear_pointer(&self->result, fl_value_unref);
  
    G_OBJECT_CLASS(fl_method_success_response_parent_class)->dispose(object);
  }
  
  static void fl_method_success_response_class_init(
      FlMethodSuccessResponseClass* klass) {
    G_OBJECT_CLASS(klass)->dispose = fl_method_success_response_dispose;
  }
  
  static void fl_method_success_response_init(FlMethodSuccessResponse* self) {}
  
  static void fl_method_error_response_dispose(GObject* object) {
    FlMethodErrorResponse* self = FL_METHOD_ERROR_RESPONSE(object);
  
    g_clear_pointer(&self->code, g_free);
    g_clear_pointer(&self->message, g_free);
    g_clear_pointer(&self->details, fl_value_unref);
  
    G_OBJECT_CLASS(fl_method_error_response_parent_class)->dispose(object);
  }
  
  static void fl_method_error_response_class_init(
      FlMethodErrorResponseClass* klass) {
    G_OBJECT_CLASS(klass)->dispose = fl_method_error_response_dispose;
  }
  
  static void fl_method_error_response_init(FlMethodErrorResponse* self) {}
  
  static void fl_method_not_implemented_response_class_init(
      FlMethodNotImplementedResponseClass* klass) {}
  
  static void fl_method_not_implemented_response_init(
      FlMethodNotImplementedResponse* self) {}
  
  G_MODULE_EXPORT FlValue* fl_method_response_get_result(FlMethodResponse* self,
                                                         GError** error) {
    if (FL_IS_METHOD_SUCCESS_RESPONSE(self)) {
      return fl_method_success_response_get_result(
          FL_METHOD_SUCCESS_RESPONSE(self));
    }
  
    if (FL_IS_METHOD_ERROR_RESPONSE(self)) {
      const gchar* code =
          fl_method_error_response_get_code(FL_METHOD_ERROR_RESPONSE(self));
      const gchar* message =
          fl_method_error_response_get_message(FL_METHOD_ERROR_RESPONSE(self));
      FlValue* details =
          fl_method_error_response_get_details(FL_METHOD_ERROR_RESPONSE(self));
      g_autofree gchar* details_text = nullptr;
      if (details != nullptr) {
        details_text = fl_value_to_string(details);
      }
  
      g_autoptr(GString) error_message = g_string_new("");
      g_string_append_printf(error_message, "Remote code returned error %s",
                             code);
      if (message != nullptr) {
        g_string_append_printf(error_message, ": %s", message);
      }
      if (details_text != nullptr) {
        g_string_append_printf(error_message, " %s", details_text);
      }
      g_set_error_literal(error, FL_METHOD_RESPONSE_ERROR,
                          FL_METHOD_RESPONSE_ERROR_REMOTE_ERROR,
                          error_message->str);
      return nullptr;
    } else if (FL_IS_METHOD_NOT_IMPLEMENTED_RESPONSE(self)) {
      g_set_error(error, FL_METHOD_RESPONSE_ERROR,
                  FL_METHOD_RESPONSE_ERROR_NOT_IMPLEMENTED,
                  "Requested method is not implemented");
      return nullptr;
    } else {
      g_set_error(error, FL_METHOD_RESPONSE_ERROR,
                  FL_METHOD_RESPONSE_ERROR_FAILED, "Unknown response type");
      return nullptr;
    }
  }
  
  G_MODULE_EXPORT FlMethodSuccessResponse* fl_method_success_response_new(
      FlValue* result) {
    FlMethodSuccessResponse* self = FL_METHOD_SUCCESS_RESPONSE(
        g_object_new(fl_method_success_response_get_type(), nullptr));
  
    if (result != nullptr) {
      self->result = fl_value_ref(result);
    }
  
    return self;
  }
  
  G_MODULE_EXPORT FlValue* fl_method_success_response_get_result(
      FlMethodSuccessResponse* self) {
    g_return_val_if_fail(FL_IS_METHOD_SUCCESS_RESPONSE(self), nullptr);
    return self->result;
  }
  
  G_MODULE_EXPORT FlMethodErrorResponse* fl_method_error_response_new(
      const gchar* code,
      const gchar* message,
      FlValue* details) {
    g_return_val_if_fail(code != nullptr, nullptr);
  
    FlMethodErrorResponse* self = FL_METHOD_ERROR_RESPONSE(
        g_object_new(fl_method_error_response_get_type(), nullptr));
  
    self->code = g_strdup(code);
    self->message = g_strdup(message);
    self->details = details != nullptr ? fl_value_ref(details) : nullptr;
  
    return self;
  }
  
  G_MODULE_EXPORT const gchar* fl_method_error_response_get_code(
      FlMethodErrorResponse* self) {
    g_return_val_if_fail(FL_IS_METHOD_ERROR_RESPONSE(self), nullptr);
    return self->code;
  }
  
  G_MODULE_EXPORT const gchar* fl_method_error_response_get_message(
      FlMethodErrorResponse* self) {
    g_return_val_if_fail(FL_IS_METHOD_ERROR_RESPONSE(self), nullptr);
    return self->message;
  }
  
  G_MODULE_EXPORT FlValue* fl_method_error_response_get_details(
      FlMethodErrorResponse* self) {
    g_return_val_if_fail(FL_IS_METHOD_ERROR_RESPONSE(self), nullptr);
    return self->details;
  }
  
  G_MODULE_EXPORT FlMethodNotImplementedResponse*
  fl_method_not_implemented_response_new() {
    return FL_METHOD_NOT_IMPLEMENTED_RESPONSE(
        g_object_new(fl_method_not_implemented_response_get_type(), nullptr));
  }
  