summaryrefslogtreecommitdiff
path: root/platform/node/src/node_style.hpp
blob: b81d14c700f1d42de88f2ff2b09651a3b010c25a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
#include <mbgl/style/property_value.hpp>
#include <mbgl/style/layer.hpp>
#include <mbgl/util/optional.hpp>
#include <mbgl/util/enum.hpp>

namespace node_mbgl {

template <class V, class Enable = void>
struct ValueConverter {};

template <>
struct ValueConverter<bool> {
    mbgl::optional<mbgl::style::PropertyValue<bool>> operator()(const v8::Local<v8::Value>& value) const {
        if (!value->IsBoolean()) {
            Nan::ThrowTypeError("boolean required");
            return {};
        }

        return { value->BooleanValue() };
    }
};

template <>
struct ValueConverter<float> {
    mbgl::optional<mbgl::style::PropertyValue<float>> operator()(const v8::Local<v8::Value>& value) const {
        if (!value->IsNumber()) {
            Nan::ThrowTypeError("number required");
            return {};
        }

        return { value->NumberValue() };
    }
};

template <>
struct ValueConverter<std::string> {
    mbgl::optional<mbgl::style::PropertyValue<std::string>> operator()(const v8::Local<v8::Value>& value) const {
        if (!value->IsString()) {
            Nan::ThrowTypeError("string required");
            return {};
        }

        return { std::string(*Nan::Utf8String(value)) };
    }
};

template <typename T>
struct ValueConverter<T, std::enable_if_t<std::is_enum<T>::value>> {
    mbgl::optional<mbgl::style::PropertyValue<T>> operator()(const v8::Local<v8::Value>& value) const {
        if (!value->IsString()) {
            Nan::ThrowTypeError("string required");
            return {};
        }

        mbgl::optional<T> result = mbgl::Enum<T>::toEnum(*Nan::Utf8String(value));
        if (!result) {
            Nan::ThrowTypeError("invalid enumeration value");
            return {};
        }

        return { *result };
    }
};

template <>
struct ValueConverter<mbgl::Color> {
    mbgl::optional<mbgl::style::PropertyValue<mbgl::Color>> operator()(const v8::Local<v8::Value>& value) const {
        (void)value;
        return {};
    }
};

template <>
struct ValueConverter<std::array<float, 2>> {
    mbgl::optional<mbgl::style::PropertyValue<std::array<float, 2>>> operator()(const v8::Local<v8::Value>& value) const {
        (void)value;
        return {};
    }
};

template <>
struct ValueConverter<std::vector<float>> {
    mbgl::optional<mbgl::style::PropertyValue<std::vector<float>>> operator()(const v8::Local<v8::Value>& value) const {
        (void)value;
        return {};
    }
};

template <>
struct ValueConverter<std::vector<std::string>> {
    mbgl::optional<mbgl::style::PropertyValue<std::vector<std::string>>> operator()(const v8::Local<v8::Value>& value) const {
        (void)value;
        return {};
    }
};

using PropertySetter = std::function<bool (mbgl::style::Layer&, const v8::Local<v8::Value>&)>;
using PropertySetters = std::unordered_map<std::string, PropertySetter>;

template <class L, class V>
PropertySetter makePropertySetter(void (L::*setter)(mbgl::style::PropertyValue<V>)) {
    return [setter] (mbgl::style::Layer& layer, const v8::Local<v8::Value>& value) {
        L* typedLayer = layer.as<L>();
        if (!typedLayer) {
            Nan::ThrowTypeError("layer doesn't support this property");
            return false;
        }

        mbgl::optional<mbgl::style::PropertyValue<V>> typedValue;

        if (value->IsNull() || value->IsUndefined()) {
            typedValue = mbgl::style::PropertyValue<V>();
        } else {
            typedValue = ValueConverter<V>()(value);
        }

        if (!typedValue) {
            return false;
        }

        (typedLayer->*setter)(*typedValue);
        return true;
    };
}

}