Add FlMessageCodec, FlBinaryCodec, FlStringCodec (#18186)

Classs for binary message encoding/decoding that matches the ones in the Flutter services library.
This commit is contained in:
Robert Ancell 2020-05-08 16:13:54 +12:00 committed by GitHub
parent 9b905d3f03
commit 9ea2db5bac
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 788 additions and 0 deletions

View File

@ -1184,22 +1184,31 @@ FILE: ../../../flutter/shell/platform/glfw/platform_handler.h
FILE: ../../../flutter/shell/platform/glfw/public/flutter_glfw.h
FILE: ../../../flutter/shell/platform/glfw/text_input_plugin.cc
FILE: ../../../flutter/shell/platform/glfw/text_input_plugin.h
FILE: ../../../flutter/shell/platform/linux/fl_binary_codec.cc
FILE: ../../../flutter/shell/platform/linux/fl_binary_codec_test.cc
FILE: ../../../flutter/shell/platform/linux/fl_binary_messenger.cc
FILE: ../../../flutter/shell/platform/linux/fl_binary_messenger_private.h
FILE: ../../../flutter/shell/platform/linux/fl_dart_project.cc
FILE: ../../../flutter/shell/platform/linux/fl_dart_project_test.cc
FILE: ../../../flutter/shell/platform/linux/fl_engine.cc
FILE: ../../../flutter/shell/platform/linux/fl_engine_private.h
FILE: ../../../flutter/shell/platform/linux/fl_message_codec.cc
FILE: ../../../flutter/shell/platform/linux/fl_message_codec_test.cc
FILE: ../../../flutter/shell/platform/linux/fl_renderer.cc
FILE: ../../../flutter/shell/platform/linux/fl_renderer.h
FILE: ../../../flutter/shell/platform/linux/fl_renderer_x11.cc
FILE: ../../../flutter/shell/platform/linux/fl_renderer_x11.h
FILE: ../../../flutter/shell/platform/linux/fl_string_codec.cc
FILE: ../../../flutter/shell/platform/linux/fl_string_codec_test.cc
FILE: ../../../flutter/shell/platform/linux/fl_value.cc
FILE: ../../../flutter/shell/platform/linux/fl_value_test.cc
FILE: ../../../flutter/shell/platform/linux/fl_view.cc
FILE: ../../../flutter/shell/platform/linux/public/flutter_linux/fl_binary_codec.h
FILE: ../../../flutter/shell/platform/linux/public/flutter_linux/fl_binary_messenger.h
FILE: ../../../flutter/shell/platform/linux/public/flutter_linux/fl_dart_project.h
FILE: ../../../flutter/shell/platform/linux/public/flutter_linux/fl_engine.h
FILE: ../../../flutter/shell/platform/linux/public/flutter_linux/fl_message_codec.h
FILE: ../../../flutter/shell/platform/linux/public/flutter_linux/fl_string_codec.h
FILE: ../../../flutter/shell/platform/linux/public/flutter_linux/fl_value.h
FILE: ../../../flutter/shell/platform/linux/public/flutter_linux/fl_view.h
FILE: ../../../flutter/shell/platform/linux/public/flutter_linux/flutter_linux.h

View File

@ -44,9 +44,12 @@ if (build_glfw_shell) {
}
_public_headers = [
"public/flutter_linux/fl_binary_codec.h",
"public/flutter_linux/fl_binary_messenger.h",
"public/flutter_linux/fl_dart_project.h",
"public/flutter_linux/fl_engine.h",
"public/flutter_linux/fl_message_codec.h",
"public/flutter_linux/fl_string_codec.h",
"public/flutter_linux/fl_value.h",
"public/flutter_linux/fl_view.h",
"public/flutter_linux/flutter_linux.h",
@ -60,11 +63,14 @@ source_set("flutter_linux") {
public = _public_headers
sources = [
"fl_binary_codec.cc",
"fl_binary_messenger.cc",
"fl_dart_project.cc",
"fl_engine.cc",
"fl_message_codec.cc",
"fl_renderer.cc",
"fl_renderer_x11.cc",
"fl_string_codec.cc",
"fl_value.cc",
"fl_view.cc",
]
@ -91,8 +97,12 @@ executable("flutter_linux_unittests") {
testonly = true
sources = [
"fl_binary_codec_test.cc",
"fl_dart_project_test.cc",
"fl_message_codec_test.cc",
"fl_string_codec_test.cc",
"fl_value_test.cc",
"testing/fl_test.cc",
]
public_configs = [ "//flutter:config" ]

View File

@ -0,0 +1,54 @@
// 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_binary_codec.h"
#include <gmodule.h>
G_DEFINE_QUARK(fl_binary_codec_error_quark, fl_binary_codec_error)
struct _FlBinaryCodec {
FlMessageCodec parent_instance;
};
G_DEFINE_TYPE(FlBinaryCodec, fl_binary_codec, fl_message_codec_get_type())
// Implements FlMessageCodec::encode_message
static GBytes* fl_binary_codec_encode_message(FlMessageCodec* codec,
FlValue* value,
GError** error) {
if (fl_value_get_type(value) != FL_VALUE_TYPE_UINT8_LIST) {
g_set_error(error, FL_MESSAGE_CODEC_ERROR,
FL_MESSAGE_CODEC_ERROR_UNSUPPORTED_TYPE,
"Only uint8[] values supported");
return nullptr;
}
return g_bytes_new(fl_value_get_uint8_list(value),
fl_value_get_length(value));
}
// Implements FlMessageCodec::decode_message
static FlValue* fl_binary_codec_decode_message(FlMessageCodec* codec,
GBytes* message,
GError** error) {
gsize data_length;
const uint8_t* data =
static_cast<const uint8_t*>(g_bytes_get_data(message, &data_length));
return fl_value_new_uint8_list(data, data_length);
}
static void fl_binary_codec_class_init(FlBinaryCodecClass* klass) {
FL_MESSAGE_CODEC_CLASS(klass)->encode_message =
fl_binary_codec_encode_message;
FL_MESSAGE_CODEC_CLASS(klass)->decode_message =
fl_binary_codec_decode_message;
}
static void fl_binary_codec_init(FlBinaryCodec* self) {}
G_MODULE_EXPORT FlBinaryCodec* fl_binary_codec_new() {
return static_cast<FlBinaryCodec*>(
g_object_new(fl_binary_codec_get_type(), nullptr));
}

View File

@ -0,0 +1,105 @@
// 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_binary_codec.h"
#include "flutter/shell/platform/linux/testing/fl_test.h"
#include "gtest/gtest.h"
// Encode a message using a FlBinaryCodec. Return a hex string with the encoded
// binary output.
static gchar* encode_message(FlValue* value) {
g_autoptr(FlBinaryCodec) codec = fl_binary_codec_new();
g_autoptr(GError) error = nullptr;
g_autoptr(GBytes) message =
fl_message_codec_encode_message(FL_MESSAGE_CODEC(codec), value, &error);
EXPECT_NE(message, nullptr);
EXPECT_EQ(error, nullptr);
return bytes_to_hex_string(message);
}
// Encode a message using a FlBinaryCodec. Expect the given error.
static void encode_message_error(FlValue* value, GQuark domain, int code) {
g_autoptr(FlBinaryCodec) codec = fl_binary_codec_new();
g_autoptr(GError) error = nullptr;
g_autoptr(GBytes) message =
fl_message_codec_encode_message(FL_MESSAGE_CODEC(codec), value, &error);
EXPECT_EQ(message, nullptr);
EXPECT_TRUE(g_error_matches(error, domain, code));
}
// Decode a message using a FlBinaryCodec. The binary data is given in the form
// of a hex string.
static FlValue* decode_message(const char* hex_string) {
g_autoptr(FlBinaryCodec) codec = fl_binary_codec_new();
g_autoptr(GBytes) data = hex_string_to_bytes(hex_string);
g_autoptr(GError) error = nullptr;
g_autoptr(FlValue) value =
fl_message_codec_decode_message(FL_MESSAGE_CODEC(codec), data, &error);
EXPECT_EQ(error, nullptr);
EXPECT_NE(value, nullptr);
return fl_value_ref(value);
}
TEST(FlBinaryCodecTest, EncodeData) {
uint8_t data[] = {0x00, 0x01, 0x02, 0xFD, 0xFE, 0xFF};
g_autoptr(FlValue) value = fl_value_new_uint8_list(data, 6);
g_autofree gchar* hex_string = encode_message(value);
EXPECT_STREQ(hex_string, "000102fdfeff");
}
TEST(FlBinaryCodecTest, EncodeEmpty) {
g_autoptr(FlValue) value = fl_value_new_uint8_list(nullptr, 0);
g_autofree gchar* hex_string = encode_message(value);
EXPECT_STREQ(hex_string, "");
}
TEST(FlBinaryCodecTest, EncodeNULL) {
encode_message_error(nullptr, FL_MESSAGE_CODEC_ERROR,
FL_MESSAGE_CODEC_ERROR_UNSUPPORTED_TYPE);
}
TEST(FlBinaryCodecTest, EncodeUnknownType) {
g_autoptr(FlValue) value = fl_value_new_null();
encode_message_error(value, FL_MESSAGE_CODEC_ERROR,
FL_MESSAGE_CODEC_ERROR_UNSUPPORTED_TYPE);
}
TEST(FlBinaryCodecTest, DecodeData) {
g_autoptr(FlValue) value = decode_message("000102fdfeff");
ASSERT_EQ(fl_value_get_type(value), FL_VALUE_TYPE_UINT8_LIST);
ASSERT_EQ(fl_value_get_length(value), static_cast<size_t>(6));
EXPECT_EQ(fl_value_get_uint8_list(value)[0], 0x00);
EXPECT_EQ(fl_value_get_uint8_list(value)[1], 0x01);
EXPECT_EQ(fl_value_get_uint8_list(value)[2], 0x02);
EXPECT_EQ(fl_value_get_uint8_list(value)[3], 0xFD);
EXPECT_EQ(fl_value_get_uint8_list(value)[4], 0xFE);
EXPECT_EQ(fl_value_get_uint8_list(value)[5], 0xFF);
}
TEST(FlBinaryCodecTest, DecodeEmpty) {
g_autoptr(FlValue) value = decode_message("");
ASSERT_EQ(fl_value_get_type(value), FL_VALUE_TYPE_UINT8_LIST);
ASSERT_EQ(fl_value_get_length(value), static_cast<size_t>(0));
}
TEST(FlBinaryCodecTest, EncodeDecode) {
g_autoptr(FlBinaryCodec) codec = fl_binary_codec_new();
uint8_t data[] = {0x00, 0x01, 0x02, 0xFD, 0xFE, 0xFF};
g_autoptr(FlValue) input = fl_value_new_uint8_list(data, 6);
g_autoptr(GError) error = nullptr;
g_autoptr(GBytes) message =
fl_message_codec_encode_message(FL_MESSAGE_CODEC(codec), input, &error);
EXPECT_NE(message, nullptr);
EXPECT_EQ(error, nullptr);
g_autoptr(FlValue) output =
fl_message_codec_decode_message(FL_MESSAGE_CODEC(codec), message, &error);
EXPECT_EQ(error, nullptr);
EXPECT_NE(output, nullptr);
ASSERT_TRUE(fl_value_equal(input, output));
}

View File

@ -0,0 +1,43 @@
// 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_message_codec.h"
#include <gmodule.h>
G_DEFINE_QUARK(fl_message_codec_error_quark, fl_message_codec_error)
// Added here to stop the compiler from optimising this function away
G_MODULE_EXPORT GType fl_message_codec_get_type();
G_DEFINE_TYPE(FlMessageCodec, fl_message_codec, G_TYPE_OBJECT)
static void fl_message_codec_class_init(FlMessageCodecClass* klass) {}
static void fl_message_codec_init(FlMessageCodec* self) {}
G_MODULE_EXPORT GBytes* fl_message_codec_encode_message(FlMessageCodec* self,
FlValue* value,
GError** error) {
g_return_val_if_fail(FL_IS_MESSAGE_CODEC(self), nullptr);
// If the user provided NULL, then make a temporary FlValue object for this to
// make it simpler for the subclasses
g_autoptr(FlValue) null_value = nullptr;
if (value == nullptr) {
null_value = fl_value_new_null();
value = null_value;
}
return FL_MESSAGE_CODEC_GET_CLASS(self)->encode_message(self, value, error);
}
G_MODULE_EXPORT FlValue* fl_message_codec_decode_message(FlMessageCodec* self,
GBytes* message,
GError** error) {
g_return_val_if_fail(FL_IS_MESSAGE_CODEC(self), nullptr);
g_return_val_if_fail(message != nullptr, nullptr);
return FL_MESSAGE_CODEC_GET_CLASS(self)->decode_message(self, message, error);
}

View File

@ -0,0 +1,133 @@
// 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_message_codec.h"
#include "gtest/gtest.h"
G_DECLARE_FINAL_TYPE(FlTestCodec, fl_test_codec, FL, TEST_CODEC, FlMessageCodec)
// Implement the FlMessageCodec API for the following tests to check it works as
// expected
struct _FlTestCodec {
FlMessageCodec parent_instance;
};
G_DEFINE_TYPE(FlTestCodec, fl_test_codec, fl_message_codec_get_type())
// Implements FlMessageCodec::encode_message
static GBytes* fl_test_codec_encode_message(FlMessageCodec* codec,
FlValue* value,
GError** error) {
EXPECT_TRUE(FL_IS_TEST_CODEC(codec));
if (fl_value_get_type(value) == FL_VALUE_TYPE_INT) {
char c = '0' + fl_value_get_int(value);
return g_bytes_new(&c, 1);
} else {
g_set_error(error, FL_MESSAGE_CODEC_ERROR, FL_MESSAGE_CODEC_ERROR_FAILED,
"ERROR");
return nullptr;
}
}
// Implements FlMessageCodec::decode_message
static FlValue* fl_test_codec_decode_message(FlMessageCodec* codec,
GBytes* message,
GError** error) {
EXPECT_TRUE(FL_IS_TEST_CODEC(codec));
size_t data_length;
const uint8_t* data =
static_cast<const uint8_t*>(g_bytes_get_data(message, &data_length));
if (data_length < 1) {
g_set_error(error, FL_MESSAGE_CODEC_ERROR,
FL_MESSAGE_CODEC_ERROR_OUT_OF_DATA, "No data");
return FALSE;
}
if (data_length > 1) {
g_set_error(error, FL_MESSAGE_CODEC_ERROR,
FL_MESSAGE_CODEC_ERROR_ADDITIONAL_DATA,
"FL_MESSAGE_CODEC_ERROR_ADDITIONAL_DATA");
return FALSE;
}
return fl_value_new_int(data[0] - '0');
}
static void fl_test_codec_class_init(FlTestCodecClass* klass) {
FL_MESSAGE_CODEC_CLASS(klass)->encode_message = fl_test_codec_encode_message;
FL_MESSAGE_CODEC_CLASS(klass)->decode_message = fl_test_codec_decode_message;
}
static void fl_test_codec_init(FlTestCodec* self) {}
static FlTestCodec* fl_test_codec_new() {
return FL_TEST_CODEC(g_object_new(fl_test_codec_get_type(), nullptr));
}
TEST(FlMessageCodecTest, EncodeMessage) {
g_autoptr(FlTestCodec) codec = fl_test_codec_new();
g_autoptr(FlValue) value = fl_value_new_int(1);
g_autoptr(GError) error = nullptr;
g_autoptr(GBytes) message =
fl_message_codec_encode_message(FL_MESSAGE_CODEC(codec), value, &error);
EXPECT_NE(message, nullptr);
EXPECT_EQ(error, nullptr);
EXPECT_EQ(g_bytes_get_size(message), static_cast<gsize>(1));
EXPECT_EQ(static_cast<const uint8_t*>(g_bytes_get_data(message, nullptr))[0],
'1');
}
TEST(FlMessageCodecTest, EncodeMessageError) {
g_autoptr(FlTestCodec) codec = fl_test_codec_new();
g_autoptr(FlValue) value = fl_value_new_null();
g_autoptr(GError) error = nullptr;
g_autoptr(GBytes) message =
fl_message_codec_encode_message(FL_MESSAGE_CODEC(codec), value, &error);
EXPECT_EQ(message, nullptr);
EXPECT_TRUE(g_error_matches(error, FL_MESSAGE_CODEC_ERROR,
FL_MESSAGE_CODEC_ERROR_FAILED));
}
TEST(FlMessageCodecTest, DecodeMessageEmpty) {
g_autoptr(FlTestCodec) codec = fl_test_codec_new();
g_autoptr(GBytes) message = g_bytes_new(nullptr, 0);
g_autoptr(GError) error = nullptr;
g_autoptr(FlValue) value =
fl_message_codec_decode_message(FL_MESSAGE_CODEC(codec), message, &error);
EXPECT_EQ(value, nullptr);
EXPECT_TRUE(g_error_matches(error, FL_MESSAGE_CODEC_ERROR,
FL_MESSAGE_CODEC_ERROR_OUT_OF_DATA));
}
TEST(FlMessageCodecTest, DecodeMessage) {
g_autoptr(FlTestCodec) codec = fl_test_codec_new();
uint8_t data[] = {'1'};
g_autoptr(GBytes) message = g_bytes_new(data, 1);
g_autoptr(GError) error = nullptr;
g_autoptr(FlValue) value =
fl_message_codec_decode_message(FL_MESSAGE_CODEC(codec), message, &error);
EXPECT_NE(value, nullptr);
EXPECT_EQ(error, nullptr);
ASSERT_TRUE(fl_value_get_type(value) == FL_VALUE_TYPE_INT);
EXPECT_EQ(fl_value_get_int(value), 1);
}
TEST(FlMessageCodecTest, DecodeMessageExtraData) {
g_autoptr(FlTestCodec) codec = fl_test_codec_new();
uint8_t data[] = {'1', '2'};
g_autoptr(GBytes) message = g_bytes_new(data, 2);
g_autoptr(GError) error = nullptr;
g_autoptr(FlValue) value =
fl_message_codec_decode_message(FL_MESSAGE_CODEC(codec), message, &error);
EXPECT_EQ(value, nullptr);
EXPECT_TRUE(g_error_matches(error, FL_MESSAGE_CODEC_ERROR,
FL_MESSAGE_CODEC_ERROR_ADDITIONAL_DATA));
}

View File

@ -0,0 +1,54 @@
// 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_string_codec.h"
#include <gmodule.h>
G_DEFINE_QUARK(fl_string_codec_error_quark, fl_string_codec_error)
struct _FlStringCodec {
FlMessageCodec parent_instance;
};
G_DEFINE_TYPE(FlStringCodec, fl_string_codec, fl_message_codec_get_type())
// Implments FlMessageCodec::encode_message
static GBytes* fl_string_codec_encode_message(FlMessageCodec* codec,
FlValue* value,
GError** error) {
if (fl_value_get_type(value) != FL_VALUE_TYPE_STRING) {
g_set_error(error, FL_MESSAGE_CODEC_ERROR,
FL_MESSAGE_CODEC_ERROR_UNSUPPORTED_TYPE,
"Only string values supported");
return nullptr;
}
const gchar* text = fl_value_get_string(value);
return g_bytes_new(text, strlen(text));
}
// Implments FlMessageCodec::decode_message
static FlValue* fl_string_codec_decode_message(FlMessageCodec* codec,
GBytes* message,
GError** error) {
gsize data_length;
const gchar* data =
static_cast<const gchar*>(g_bytes_get_data(message, &data_length));
return fl_value_new_string_sized(data, data_length);
}
static void fl_string_codec_class_init(FlStringCodecClass* klass) {
FL_MESSAGE_CODEC_CLASS(klass)->encode_message =
fl_string_codec_encode_message;
FL_MESSAGE_CODEC_CLASS(klass)->decode_message =
fl_string_codec_decode_message;
}
static void fl_string_codec_init(FlStringCodec* self) {}
G_MODULE_EXPORT FlStringCodec* fl_string_codec_new() {
return static_cast<FlStringCodec*>(
g_object_new(fl_string_codec_get_type(), nullptr));
}

View File

@ -0,0 +1,97 @@
// 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_string_codec.h"
#include "flutter/shell/platform/linux/testing/fl_test.h"
#include "gtest/gtest.h"
// Encode a message using a FlStringCodec. Return a hex string with the encoded
// binary output.
static gchar* encode_message(FlValue* value) {
g_autoptr(FlStringCodec) codec = fl_string_codec_new();
g_autoptr(GError) error = nullptr;
g_autoptr(GBytes) message =
fl_message_codec_encode_message(FL_MESSAGE_CODEC(codec), value, &error);
EXPECT_NE(message, nullptr);
EXPECT_EQ(error, nullptr);
return bytes_to_hex_string(message);
}
// Encode a message using a FlStringCodec. Expect the given error.
static void encode_message_error(FlValue* value, GQuark domain, int code) {
g_autoptr(FlStringCodec) codec = fl_string_codec_new();
g_autoptr(GError) error = nullptr;
g_autoptr(GBytes) message =
fl_message_codec_encode_message(FL_MESSAGE_CODEC(codec), value, &error);
EXPECT_EQ(message, nullptr);
EXPECT_TRUE(g_error_matches(error, domain, code));
}
// Decode a message using a FlStringCodec. The binary data is given in the form
// of a hex string.
static FlValue* decode_message(const char* hex_string) {
g_autoptr(FlStringCodec) codec = fl_string_codec_new();
g_autoptr(GBytes) message = hex_string_to_bytes(hex_string);
g_autoptr(GError) error = nullptr;
g_autoptr(FlValue) value =
fl_message_codec_decode_message(FL_MESSAGE_CODEC(codec), message, &error);
EXPECT_EQ(error, nullptr);
EXPECT_NE(value, nullptr);
return fl_value_ref(value);
}
TEST(FlStringCodecTest, EncodeData) {
g_autoptr(FlValue) value = fl_value_new_string("hello");
g_autofree gchar* hex_string = encode_message(value);
EXPECT_STREQ(hex_string, "68656c6c6f");
}
TEST(FlStringCodecTest, EncodeEmpty) {
g_autoptr(FlValue) value = fl_value_new_string("");
g_autofree gchar* hex_string = encode_message(value);
EXPECT_STREQ(hex_string, "");
}
TEST(FlStringCodecTest, EncodeNULL) {
encode_message_error(nullptr, FL_MESSAGE_CODEC_ERROR,
FL_MESSAGE_CODEC_ERROR_UNSUPPORTED_TYPE);
}
TEST(FlStringCodecTest, EncodeUnknownType) {
g_autoptr(FlValue) value = fl_value_new_null();
encode_message_error(value, FL_MESSAGE_CODEC_ERROR,
FL_MESSAGE_CODEC_ERROR_UNSUPPORTED_TYPE);
}
TEST(FlStringCodecTest, DecodeData) {
g_autoptr(FlValue) value = decode_message("68656c6c6f");
ASSERT_EQ(fl_value_get_type(value), FL_VALUE_TYPE_STRING);
ASSERT_STREQ(fl_value_get_string(value), "hello");
}
TEST(FlStringCodecTest, DecodeEmpty) {
g_autoptr(FlValue) value = decode_message("");
ASSERT_EQ(fl_value_get_type(value), FL_VALUE_TYPE_STRING);
ASSERT_STREQ(fl_value_get_string(value), "");
}
TEST(FlStringCodecTest, EncodeDecode) {
g_autoptr(FlStringCodec) codec = fl_string_codec_new();
g_autoptr(FlValue) input = fl_value_new_string("hello");
g_autoptr(GError) error = nullptr;
g_autoptr(GBytes) message =
fl_message_codec_encode_message(FL_MESSAGE_CODEC(codec), input, &error);
EXPECT_NE(message, nullptr);
EXPECT_EQ(error, nullptr);
g_autoptr(FlValue) output =
fl_message_codec_decode_message(FL_MESSAGE_CODEC(codec), message, &error);
EXPECT_EQ(error, nullptr);
EXPECT_NE(output, nullptr);
ASSERT_TRUE(fl_value_equal(input, output));
}

View File

@ -0,0 +1,44 @@
// 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.
#ifndef FLUTTER_SHELL_PLATFORM_LINUX_FL_BINARY_CODEC_H_
#define FLUTTER_SHELL_PLATFORM_LINUX_FL_BINARY_CODEC_H_
#if !defined(__FLUTTER_LINUX_INSIDE__) && !defined(FLUTTER_LINUX_COMPILATION)
#error "Only <flutter_linux/flutter_linux.h> can be included directly."
#endif
#include "fl_message_codec.h"
G_BEGIN_DECLS
G_DECLARE_FINAL_TYPE(FlBinaryCodec,
fl_standard_codec,
FL,
BINARY_CODEC,
FlMessageCodec)
/**
* FlBinaryCodec:
*
* #FlBinaryCodec is a #FlMessageCodec that implements the Flutter binary
* message encoding. This encodes and decodes #FlValue of type
* #FL_VALUE_TYPE_UINT8_LIST.
*
* #FlBinaryCodec matches the BinaryCodec class in the Flutter services
* library.
*/
/**
* fl_binary_codec_new:
*
* Creates a #FlBinaryCodec.
*
* Returns: a new #FlBinaryCodec.
*/
FlBinaryCodec* fl_binary_codec_new();
G_END_DECLS
#endif // FLUTTER_SHELL_PLATFORM_LINUX_FL_BINARY_CODEC_H_

View File

@ -0,0 +1,127 @@
// 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.
#ifndef FLUTTER_SHELL_PLATFORM_LINUX_FL_MESSAGE_CODEC_H_
#define FLUTTER_SHELL_PLATFORM_LINUX_FL_MESSAGE_CODEC_H_
#if !defined(__FLUTTER_LINUX_INSIDE__) && !defined(FLUTTER_LINUX_COMPILATION)
#error "Only <flutter_linux/flutter_linux.h> can be included directly."
#endif
#include <glib-object.h>
#include "fl_value.h"
G_BEGIN_DECLS
/**
* FlMessageCodecError:
* @FL_MESSAGE_CODEC_ERROR_FAILED: Codec failed due to an unspecified error
* @FL_MESSAGE_CODEC_ERROR_OUT_OF_DATA: Codec ran out of data reading a value
* @FL_MESSAGE_CODEC_ERROR_ADDITIONAL_DATA: Additional data encountered in
* message
* @FL_MESSAGE_CODEC_ERROR_UNSUPPORTED_TYPE: Codec encountered an unsupported
* #FlValue
*
* Errors for #FlMessageCodec objects to set on failures.
*/
#define FL_MESSAGE_CODEC_ERROR fl_message_codec_error_quark()
typedef enum {
FL_MESSAGE_CODEC_ERROR_FAILED,
FL_MESSAGE_CODEC_ERROR_OUT_OF_DATA,
FL_MESSAGE_CODEC_ERROR_ADDITIONAL_DATA,
FL_MESSAGE_CODEC_ERROR_UNSUPPORTED_TYPE,
} FlMessageCodecError;
GQuark fl_message_codec_error_quark(void) G_GNUC_CONST;
G_DECLARE_DERIVABLE_TYPE(FlMessageCodec,
fl_message_codec,
FL,
MESSAGE_CODEC,
GObject)
/**
* FlMessageCodec:
*
* #FlMessageCodec is a message encoding/decoding mechanism that operates on
* #FlValue objects. Both operations returns errors if the conversion fails.
* Such situations should be treated as programming errors.
*
* #FlMessageCodec matches the MethodCodec class in the Flutter services
* library.
*/
struct _FlMessageCodecClass {
GObjectClass parent_class;
/**
* FlMessageCodec::encode_message:
* @codec: A #FlMessageCodec
* @value: value to encode or %NULL to encode the null value
* @error: (allow-none): #GError location to store the error occurring, or
* %NULL
*
* Virtual method to encode a message. A subclass must implement this method.
* If the subclass cannot handle the type of @value then it must generate a
* FL_MESSAGE_CODEC_ERROR_UNSUPPORTED_TYPE error.
*
* Returns: a binary message or %NULL on error.
*/
GBytes* (*encode_message)(FlMessageCodec* codec,
FlValue* value,
GError** error);
/**
* FlMessageCodec::decode_message:
* @codec: a #FlMessageCodec
* @message: binary message to decode
* @error: (allow-none): #GError location to store the error occurring, or
* %NULL
*
* Virtual method to decode a message. A subclass must implement this method.
* If @message is too small then a #FL_MESSAGE_CODEC_ERROR_OUT_OF_DATA error
* must be generated. If @message is too large then a
* #FL_MESSAGE_CODEC_ERROR_ADDITIONAL_DATA error must be generated.
*
* Returns: a #FlValue or %NULL on error.
*/
FlValue* (*decode_message)(FlMessageCodec* codec,
GBytes* message,
GError** error);
};
/**
* fl_message_codec_encode_message:
* @codec: a #FlMessageCodec
* @buffer: buffer to write to
* @value: value to encode or %NULL to encode the null value.
* @error: (allow-none): #GError location to store the error occurring, or %NULL
*
* Encode a value into a binary representation.
*
* Returns: a binary message or %NULL on error.
*/
GBytes* fl_message_codec_encode_message(FlMessageCodec* codec,
FlValue* value,
GError** error);
/**
* fl_message_codec_decode_message:
* @codec: a #FlMessageCodec
* @message: binary message to decode
* @error: (allow-none): #GError location to store the error occurring, or %NULL
*
* Decode a value from a binary encoding.
*
* Returns: a #FlValue or %NULL on error.
*/
FlValue* fl_message_codec_decode_message(FlMessageCodec* codec,
GBytes* message,
GError** error);
G_END_DECLS
#endif // FLUTTER_SHELL_PLATFORM_LINUX_FL_MESSAGE_CODEC_H_

View File

@ -0,0 +1,43 @@
// 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.
#ifndef FLUTTER_SHELL_PLATFORM_LINUX_FL_STRING_CODEC_H_
#define FLUTTER_SHELL_PLATFORM_LINUX_FL_STRING_CODEC_H_
#if !defined(__FLUTTER_LINUX_INSIDE__) && !defined(FLUTTER_LINUX_COMPILATION)
#error "Only <flutter_linux/flutter_linux.h> can be included directly."
#endif
#include "fl_message_codec.h"
G_BEGIN_DECLS
G_DECLARE_FINAL_TYPE(FlStringCodec,
fl_string_codec,
FL,
STRING_CODEC,
FlMessageCodec)
/**
* FlStringCodec:
*
* #FlStringCodec is a #FlMessageCodec that implements the Flutter string
* message encoding. This encodes and decodes #FlValue of type
* #FL_VALUE_TYPE_STRING.
*
* #FlStringCodec matches the StringCodec class in the Flutter services library.
*/
/**
* fl_string_codec_new:
*
* Creates a #FlStringCodec.
*
* Returns: a new #FlStringCodec.
*/
FlStringCodec* fl_string_codec_new();
G_END_DECLS
#endif // FLUTTER_SHELL_PLATFORM_LINUX_FL_STRING_CODEC_H_

View File

@ -33,6 +33,8 @@ G_BEGIN_DECLS
* - #FL_VALUE_TYPE_FLOAT_LIST: Float64List
* - #FL_VALUE_TYPE_LIST: List
* - #FL_VALUE_TYPE_MAP: Map
*
* See #FlMessageCodec to encode and decode these values to a binary form.
*/
typedef struct _FlValue FlValue;

View File

@ -7,9 +7,12 @@
#define __FLUTTER_LINUX_INSIDE__
#include <flutter_linux/fl_binary_codec.h>
#include <flutter_linux/fl_binary_messenger.h>
#include <flutter_linux/fl_dart_project.h>
#include <flutter_linux/fl_engine.h>
#include <flutter_linux/fl_message_codec.h>
#include <flutter_linux/fl_string_codec.h>
#include <flutter_linux/fl_value.h>
#include <flutter_linux/fl_view.h>

View File

@ -0,0 +1,41 @@
// 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/testing/fl_test.h"
static uint8_t hex_digit_to_int(char value) {
if (value >= '0' && value <= '9')
return value - '0';
else if (value >= 'a' && value <= 'f')
return value - 'a' + 10;
else if (value >= 'F' && value <= 'F')
return value - 'A' + 10;
else
return 0;
}
static uint8_t parse_hex8(const gchar* hex_string) {
if (hex_string[0] == '\0')
return 0x00;
return hex_digit_to_int(hex_string[0]) << 4 | hex_digit_to_int(hex_string[1]);
}
GBytes* hex_string_to_bytes(const gchar* hex_string) {
GByteArray* buffer = g_byte_array_new();
for (int i = 0; hex_string[i] != '\0' && hex_string[i + 1] != '\0'; i += 2) {
uint8_t value = parse_hex8(hex_string + i);
g_byte_array_append(buffer, &value, 1);
}
return g_byte_array_free_to_bytes(buffer);
}
gchar* bytes_to_hex_string(GBytes* bytes) {
GString* hex_string = g_string_new("");
size_t data_length;
const uint8_t* data =
static_cast<const uint8_t*>(g_bytes_get_data(bytes, &data_length));
for (size_t i = 0; i < data_length; i++)
g_string_append_printf(hex_string, "%02x", data[i]);
return g_string_free(hex_string, FALSE);
}

View File

@ -0,0 +1,23 @@
// 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.
#ifndef FLUTTER_SHELL_PLATFORM_LINUX_FL_TEST_H_
#define FLUTTER_SHELL_PLATFORM_LINUX_FL_TEST_H_
#include <glib.h>
#include <stdint.h>
G_BEGIN_DECLS
// Helper functions for the tests. This is not included in the shell library.
// Helper function to convert a hexadecimal string (e.g. "01feab") into GBytes
GBytes* hex_string_to_bytes(const gchar* hex_string);
// Helper function to convert GBytes into a hexadecimal string (e.g. "01feab")
gchar* bytes_to_hex_string(GBytes* bytes);
G_END_DECLS
#endif // FLUTTER_SHELL_PLATFORM_LINUX_FL_TEST_H_