#include "node_feature.hpp" namespace node_mbgl { using namespace mapbox::geometry; using Value = mbgl::Value; using Feature = mbgl::Feature; using FeatureIdentifier = mbgl::FeatureIdentifier; using Geometry = mbgl::Feature::geometry_type; using GeometryCollection = mapbox::geometry::geometry_collection; using Properties = mbgl::PropertyMap; template struct ToType { public: v8::Local operator()(const point&) { return type("Point"); } v8::Local operator()(const line_string&) { return type("LineString"); } v8::Local operator()(const polygon&) { return type("Polygon"); } v8::Local operator()(const multi_point&) { return type("MultiPoint"); } v8::Local operator()(const multi_line_string&) { return type("MultiLineString"); } v8::Local operator()(const multi_polygon&) { return type("MultiPolygon"); } v8::Local operator()(const geometry_collection&) { return type("GeometryCollection"); } private: v8::Local type(const char* type) { Nan::EscapableHandleScope scope; return scope.Escape(Nan::New(type).ToLocalChecked()); } }; template struct ToCoordinatesOrGeometries { public: // Handles line_string, polygon, multi_point, multi_line_string, multi_polygon, and geometry_collection. template v8::Local operator()(const std::vector& vector) { Nan::EscapableHandleScope scope; v8::Local result = Nan::New(vector.size()); for (std::size_t i = 0; i < vector.size(); ++i) { Nan::Set(result, i, operator()(vector[i])); } return scope.Escape(result); } v8::Local operator()(const point& point) { Nan::EscapableHandleScope scope; v8::Local result = Nan::New(2); Nan::Set(result, 0, Nan::New(point.x)); Nan::Set(result, 1, Nan::New(point.y)); return scope.Escape(result); } v8::Local operator()(const geometry& geometry) { return toJS(geometry); } }; struct ToValue { v8::Local operator()(mbgl::NullValue) { Nan::EscapableHandleScope scope; return scope.Escape(Nan::Null()); } v8::Local operator()(bool t) { Nan::EscapableHandleScope scope; return scope.Escape(Nan::New(t)); } v8::Local operator()(int64_t t) { return operator()(double(t)); } v8::Local operator()(uint64_t t) { return operator()(double(t)); } v8::Local operator()(double t) { Nan::EscapableHandleScope scope; return scope.Escape(Nan::New(t)); } v8::Local operator()(const std::string& t) { Nan::EscapableHandleScope scope; return scope.Escape(Nan::New(t).ToLocalChecked()); } v8::Local operator()(const std::vector& array) { Nan::EscapableHandleScope scope; v8::Local result = Nan::New(); for (unsigned int i = 0; i < array.size(); i++) { result->Set(i, toJS(array[i])); } return scope.Escape(result); } v8::Local operator()(const std::unordered_map& map) { return toJS(map); } }; v8::Local toJS(const Geometry& geometry) { Nan::EscapableHandleScope scope; v8::Local result = Nan::New(); Nan::Set(result, Nan::New("type").ToLocalChecked(), Geometry::visit(geometry, ToType())); Nan::Set(result, Nan::New(geometry.is() ? "geometries" : "coordinates").ToLocalChecked(), Geometry::visit(geometry, ToCoordinatesOrGeometries())); return scope.Escape(result); } v8::Local toJS(const Value& value) { return Value::visit(value, ToValue()); } v8::Local toJS(const Properties& properties) { Nan::EscapableHandleScope scope; v8::Local result = Nan::New(); for (const auto& property : properties) { Nan::Set(result, Nan::New(property.first).ToLocalChecked(), toJS(property.second)); } return scope.Escape(result); } v8::Local toJS(const Feature& feature) { Nan::EscapableHandleScope scope; v8::Local result = Nan::New(); Nan::Set(result, Nan::New("type").ToLocalChecked(), Nan::New("Feature").ToLocalChecked()); Nan::Set(result, Nan::New("geometry").ToLocalChecked(), toJS(feature.geometry)); Nan::Set(result, Nan::New("properties").ToLocalChecked(), toJS(feature.properties)); if (feature.id) { Nan::Set(result, Nan::New("id").ToLocalChecked(), FeatureIdentifier::visit(*feature.id, ToValue())); } return scope.Escape(result); } } // namespace node_mbgl