mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
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:
parent
9b905d3f03
commit
9ea2db5bac
@ -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
|
||||
|
||||
@ -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" ]
|
||||
|
||||
54
shell/platform/linux/fl_binary_codec.cc
Normal file
54
shell/platform/linux/fl_binary_codec.cc
Normal 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));
|
||||
}
|
||||
105
shell/platform/linux/fl_binary_codec_test.cc
Normal file
105
shell/platform/linux/fl_binary_codec_test.cc
Normal 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));
|
||||
}
|
||||
43
shell/platform/linux/fl_message_codec.cc
Normal file
43
shell/platform/linux/fl_message_codec.cc
Normal 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);
|
||||
}
|
||||
133
shell/platform/linux/fl_message_codec_test.cc
Normal file
133
shell/platform/linux/fl_message_codec_test.cc
Normal 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));
|
||||
}
|
||||
54
shell/platform/linux/fl_string_codec.cc
Normal file
54
shell/platform/linux/fl_string_codec.cc
Normal 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));
|
||||
}
|
||||
97
shell/platform/linux/fl_string_codec_test.cc
Normal file
97
shell/platform/linux/fl_string_codec_test.cc
Normal 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));
|
||||
}
|
||||
44
shell/platform/linux/public/flutter_linux/fl_binary_codec.h
Normal file
44
shell/platform/linux/public/flutter_linux/fl_binary_codec.h
Normal 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_
|
||||
127
shell/platform/linux/public/flutter_linux/fl_message_codec.h
Normal file
127
shell/platform/linux/public/flutter_linux/fl_message_codec.h
Normal 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_
|
||||
43
shell/platform/linux/public/flutter_linux/fl_string_codec.h
Normal file
43
shell/platform/linux/public/flutter_linux/fl_string_codec.h
Normal 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_
|
||||
@ -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;
|
||||
|
||||
|
||||
@ -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>
|
||||
|
||||
|
||||
41
shell/platform/linux/testing/fl_test.cc
Normal file
41
shell/platform/linux/testing/fl_test.cc
Normal 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);
|
||||
}
|
||||
23
shell/platform/linux/testing/fl_test.h
Normal file
23
shell/platform/linux/testing/fl_test.h
Normal 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_
|
||||
Loading…
x
Reference in New Issue
Block a user