Toast Engine
Loading...
Searching...
No Matches
data_value.hpp
Go to the documentation of this file.
1
8
9#pragma once
10
11#include <any>
12#include <glm/vec2.hpp>
13#include <glm/vec3.hpp>
14#include <glm/vec4.hpp>
15#include <map>
16#include <nlohmann/json.hpp>
17#include <optional>
18#include <string>
19#include <toast/export.hpp>
20#include <toast/log.hpp>
21#include <toast/uid.hpp>
22#include <toml++/toml.hpp>
23#include <vector>
24
25using json_t = nlohmann::json;
26
27namespace assets {
28
29enum class DataType : uint8_t {
30 null, // empty
31 bool_t, // bool
32 int_t, // int64_t
33 float_t, // double
34 string_t, // std::string
35 node_t, // toast::UID
36 asset_t, // toast::UID
37 vec2_t, // glm::vec2
38 vec3_t, // glm::vec3
39 color3_t, // glm::vec3
40 color4_t, // glm::vec4
41 array_t, // std::vector<DataValue>
42 object_t, // DataValue::ObjectMap
43};
44
45struct SchemaField;
46
50class TOAST_API DataValue {
51public:
52 using ObjectMap = std::vector<std::pair<std::string, DataValue>>;
53 using Array = std::vector<DataValue>;
54
55 DataValue() = default;
56
57 explicit DataValue(bool v) : m_type(DataType::bool_t), m_value(v) { }
58
59 explicit DataValue(int64_t v) : m_type(DataType::int_t), m_value(v) { }
60
61 explicit DataValue(double v) : m_type(DataType::float_t), m_value(v) { }
62
63 explicit DataValue(std::string v) : m_type(DataType::string_t), m_value(std::move(v)) { }
64
65 DataValue(toast::UID v, DataType kind) : m_type(kind), m_value(v) {
66 TOAST_ASSERT(
67 kind == DataType::node_t || kind == DataType::asset_t, "DataValue", "UID constructor requires Node or Asset DataType"
68 );
69 }
70
71 explicit DataValue(glm::vec2 v) : m_type(DataType::vec2_t), m_value(v) { }
72
73 DataValue(glm::vec3 v, DataType kind) : m_type(kind), m_value(v) {
74 TOAST_ASSERT(
75 kind == DataType::vec3_t || kind == DataType::color3_t, "DataValue", "vec3 constructor requires Vec3 or Color3 DataType"
76 );
77 }
78
79 explicit DataValue(glm::vec4 v) : m_type(DataType::color4_t), m_value(v) { }
80
81 static auto makeArray() -> DataValue;
82 static auto makeObject() -> DataValue;
83
84 [[nodiscard]]
85 auto type() const noexcept -> DataType {
86 return m_type;
87 }
88
89 [[nodiscard]]
90 auto isNull() const noexcept -> bool {
91 return m_type == DataType::null;
92 }
93
94 [[nodiscard]]
95 auto isArray() const noexcept -> bool {
96 return m_type == DataType::array_t;
97 }
98
99 [[nodiscard]]
100 auto isObject() const noexcept -> bool {
101 return m_type == DataType::object_t;
102 }
103
104 template<class T>
105 [[nodiscard]]
106 auto as() const -> T {
107 TOAST_ASSERT(m_value.has_value(), "DataValue", "as<T>() called on a Null DataValue");
108 if constexpr (std::is_same_v<T, std::string_view>) {
109 // Strings are stored as std::string; the view points into it and lives as long as this DataValue
110 if (const auto* str = std::any_cast<std::string>(&m_value)) {
111 return T {*str};
112 }
113 } else if constexpr (std::is_same_v<T, float>) {
114 if (const auto* ptr = std::any_cast<float>(&m_value)) {
115 return *ptr;
116 }
117 if (const auto* ptr = std::any_cast<double>(&m_value)) {
118 return static_cast<float>(*ptr);
119 }
120 } else if (const T* ptr = std::any_cast<T>(&m_value)) {
121 return *ptr;
122 }
123 TOAST_ASSERT(
124 false,
125 "DataValue",
126 "Type mismatch in DataValue::as<{}>(): requested '{}', but m_value contains '{}'",
127 typeid(T).name(),
128 typeid(T).name(),
129 m_value.type().name()
130 );
131 return T {};
132 }
133
134 template<class T>
135 [[nodiscard]]
136 auto value() const -> std::optional<T> {
137 if (!m_value.has_value()) {
138 return std::nullopt;
139 }
140 if (const T* ptr = std::any_cast<T>(&m_value)) {
141 return *ptr;
142 }
143 TOAST_WARN("DataValue", "Type mismatch in DataValue::value<T>()");
144 return std::nullopt;
145 }
146
147 explicit operator bool() const;
148 explicit operator int64_t() const;
149 explicit operator int() const;
150 explicit operator float() const;
151 explicit operator double() const;
152 explicit operator std::string() const;
153 explicit operator toast::UID() const;
154 explicit operator glm::vec2() const;
155 explicit operator glm::vec3() const;
156 explicit operator glm::vec4() const;
157
158 auto operator[](std::string_view key) -> DataValue&;
159 auto operator[](std::string_view key) const -> const DataValue&;
160
161 [[nodiscard]]
162 auto contains(std::string_view key) const noexcept -> bool;
163
164 auto operator[](size_t index) -> DataValue&;
165 auto operator[](size_t index) const -> const DataValue&;
166
167 [[nodiscard]]
168 auto size() const noexcept -> size_t;
169
170 [[nodiscard]]
171 auto empty() const noexcept -> bool {
172 return size() == 0;
173 }
174
175 void push(DataValue v);
176 void set(std::string key, DataValue v);
177 void remove(std::string_view key);
178
179 [[nodiscard]]
180 auto items() -> ObjectMap&;
181 [[nodiscard]]
182 auto items() const -> const ObjectMap&;
183
184 auto operator=(bool v) -> DataValue&;
185 auto operator=(int64_t v) -> DataValue&;
186 auto operator=(int v) -> DataValue&;
187 auto operator=(double v) -> DataValue&;
188 auto operator=(float v) -> DataValue&;
189 auto operator=(std::string v) -> DataValue&;
190
194 static auto fromToml(const toml::node& n, const SchemaField* field, const toml::table* root = nullptr) -> DataValue;
195
199 static auto fromObject(const toml::table& t, const std::vector<SchemaField>& fields, const toml::table* root = nullptr)
200 -> DataValue;
201
203 void appendTo(toml::table& tbl, const std::string& key) const;
204
206 void appendTo(toml::array& arr) const;
207
209 [[nodiscard]]
210 auto asTomlTable() const -> toml::table;
211
212 // used as the intermediate for BSON
213 [[nodiscard]]
214 auto toJson() const -> json_t;
215
217 static auto fromJson(const json_t& j, DataType hint = DataType::null) -> DataValue;
218
219private:
220 DataType m_type {DataType::null};
221 std::any m_value;
222};
223
224}
auto asTomlTable() const -> toml::table
Definition data_value.cpp:568
static auto fromObject(const toml::table &t, const std::vector< SchemaField > &fields, const toml::table *root=nullptr) -> DataValue
Build an Object DataValue from a TOML table, guided by a field list.
Definition data_value.cpp:422
void push(DataValue v)
Array: appends an element.
Definition data_value.cpp:153
void set(std::string key, DataValue v)
Object: inserts or replaces by key.
Definition data_value.cpp:158
static auto fromJson(const json_t &j, DataType hint=DataType::null) -> DataValue
Definition data_value.cpp:618
static auto fromToml(const toml::node &n, const SchemaField *field, const toml::table *root=nullptr) -> DataValue
Parse a DataValue from a TOML node, using the schema field for type context.
Definition data_value.cpp:242
void appendTo(toml::table &tbl, const std::string &key) const
Definition data_value.cpp:468
void remove(std::string_view key)
Object: removes a key (no-op if absent).
Definition data_value.cpp:170
Public logging interface for the engine.
#define TOAST_WARN(sink,...)
Indicates possible code missuse.
Definition log.hpp:94
Descriptor for one field in a schema.
Definition schema.hpp:35
Definition uid.hpp:20
Unique identifier for everything that exists in our engine.