blob: ccdd2422abed63f18e58b28dbd41bd986c5c078b [file] [log] [blame] [edit]
// 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_FML_DART_DART_CONVERTER_H_
#define FLUTTER_FML_DART_DART_CONVERTER_H_
#include <memory>
#include <vector>
#include "flutter/fml/mapping.h"
#include "third_party/dart/runtime/include/dart_api.h"
#include "third_party/tonic/converter/dart_converter.h"
namespace tonic {
using DartConverterMapping = std::unique_ptr<fml::Mapping>;
template <>
struct DartConverter<DartConverterMapping> {
static Dart_Handle ToDart(const DartConverterMapping& val) {
if (!val) {
return Dart_Null();
}
auto dart_list_handle = Dart_NewListOfTypeFilled(
ToDartTypeHandle<size_t>(), // type
CreateZeroInitializedDartObject<size_t>(), // sentinel
val->GetSize() // size
);
if (Dart_IsError(dart_list_handle)) {
FML_LOG(ERROR) << "Error while attempting to allocate a list: "
<< Dart_GetError(dart_list_handle);
return dart_list_handle;
}
if (val->GetSize() == 0) {
// Nothing to copy. Just return the zero sized list.
return dart_list_handle;
}
auto result = Dart_ListSetAsBytes(dart_list_handle, // list
0, // offset
val->GetMapping(), // native array,
val->GetSize() // length
);
if (Dart_IsError(result)) {
FML_LOG(ERROR) << "Error while attempting to create a Dart list: "
<< Dart_GetError(result);
return result;
}
return dart_list_handle;
}
static void SetReturnValue(Dart_NativeArguments args,
const DartConverterMapping& val) {
Dart_SetReturnValue(args, ToDart(val));
}
static DartConverterMapping FromDart(Dart_Handle dart_list) {
if (Dart_IsNull(dart_list)) {
return nullptr;
}
if (Dart_IsError(dart_list)) {
FML_LOG(ERROR) << "Cannot convert an error handle to a list: "
<< Dart_GetError(dart_list);
return nullptr;
}
if (!Dart_IsList(dart_list)) {
FML_LOG(ERROR) << "Dart handle was not a list.";
return nullptr;
}
intptr_t length = 0;
auto handle = Dart_ListLength(dart_list, &length);
if (Dart_IsError(handle)) {
FML_LOG(ERROR) << "Could not get the length of the Dart list: "
<< Dart_GetError(handle);
return nullptr;
}
if (length == 0) {
// Return a valid zero sized mapping.
return std::make_unique<fml::NonOwnedMapping>(nullptr, 0);
}
auto mapping_buffer = ::malloc(length);
if (!mapping_buffer) {
FML_LOG(ERROR)
<< "Out of memory while attempting to allocate a mapping of size: "
<< length;
return nullptr;
}
auto mapping = std::make_unique<fml::NonOwnedMapping>(
static_cast<const uint8_t*>(mapping_buffer), length,
[](const uint8_t* data, size_t size) {
::free(const_cast<uint8_t*>(data));
});
handle = Dart_ListGetAsBytes(
dart_list, // list
0, // offset
static_cast<uint8_t*>(mapping_buffer), // native array
length // length
);
if (Dart_IsError(handle)) {
FML_LOG(ERROR) << "Could not copy Dart list to native buffer: "
<< Dart_GetError(handle);
return nullptr;
}
return mapping;
}
};
} // namespace tonic
#endif // FLUTTER_FML_DART_DART_CONVERTER_H_