summaryrefslogtreecommitdiffstats
path: root/core/io/marshalls.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'core/io/marshalls.cpp')
-rw-r--r--core/io/marshalls.cpp405
1 files changed, 261 insertions, 144 deletions
diff --git a/core/io/marshalls.cpp b/core/io/marshalls.cpp
index d425af0afd..45b10b50bc 100644
--- a/core/io/marshalls.cpp
+++ b/core/io/marshalls.cpp
@@ -35,8 +35,6 @@
#include "core/io/resource_loader.h"
#include "core/object/ref_counted.h"
#include "core/object/script_language.h"
-#include "core/os/keyboard.h"
-#include "core/string/print_string.h"
#include <limits.h>
#include <stdio.h>
@@ -71,10 +69,31 @@ ObjectID EncodedObjectAsID::get_object_id() const {
// For `Variant::ARRAY`.
// Occupies bits 16 and 17.
#define HEADER_DATA_FIELD_TYPED_ARRAY_MASK (0b11 << 16)
-#define HEADER_DATA_FIELD_TYPED_ARRAY_NONE (0b00 << 16)
-#define HEADER_DATA_FIELD_TYPED_ARRAY_BUILTIN (0b01 << 16)
-#define HEADER_DATA_FIELD_TYPED_ARRAY_CLASS_NAME (0b10 << 16)
-#define HEADER_DATA_FIELD_TYPED_ARRAY_SCRIPT (0b11 << 16)
+#define HEADER_DATA_FIELD_TYPED_ARRAY_SHIFT 16
+
+// For `Variant::DICTIONARY`.
+// Occupies bits 16 and 17.
+#define HEADER_DATA_FIELD_TYPED_DICTIONARY_KEY_MASK (0b11 << 16)
+#define HEADER_DATA_FIELD_TYPED_DICTIONARY_KEY_SHIFT 16
+// Occupies bits 18 and 19.
+#define HEADER_DATA_FIELD_TYPED_DICTIONARY_VALUE_MASK (0b11 << 18)
+#define HEADER_DATA_FIELD_TYPED_DICTIONARY_VALUE_SHIFT 18
+
+enum ContainerTypeKind {
+ CONTAINER_TYPE_KIND_NONE = 0b00,
+ CONTAINER_TYPE_KIND_BUILTIN = 0b01,
+ CONTAINER_TYPE_KIND_CLASS_NAME = 0b10,
+ CONTAINER_TYPE_KIND_SCRIPT = 0b11,
+};
+
+struct ContainerType {
+ Variant::Type builtin_type = Variant::NIL;
+ StringName class_name;
+ Ref<Script> script;
+};
+
+#define GET_CONTAINER_TYPE_KIND(m_header, m_field) \
+ ((ContainerTypeKind)(((m_header) & HEADER_DATA_FIELD_##m_field##_MASK) >> HEADER_DATA_FIELD_##m_field##_SHIFT))
static Error _decode_string(const uint8_t *&buf, int &len, int *r_len, String &r_string) {
ERR_FAIL_COND_V(len < 4, ERR_INVALID_DATA);
@@ -82,7 +101,7 @@ static Error _decode_string(const uint8_t *&buf, int &len, int *r_len, String &r
int32_t strlen = decode_uint32(buf);
int32_t pad = 0;
- // Handle padding
+ // Handle padding.
if (strlen % 4) {
pad = 4 - strlen % 4;
}
@@ -90,7 +109,7 @@ static Error _decode_string(const uint8_t *&buf, int &len, int *r_len, String &r
buf += 4;
len -= 4;
- // Ensure buffer is big enough
+ // Ensure buffer is big enough.
ERR_FAIL_ADD_OF(strlen, pad, ERR_FILE_EOF);
ERR_FAIL_COND_V(strlen < 0 || strlen + pad > len, ERR_FILE_EOF);
@@ -98,10 +117,10 @@ static Error _decode_string(const uint8_t *&buf, int &len, int *r_len, String &r
ERR_FAIL_COND_V(str.parse_utf8((const char *)buf, strlen) != OK, ERR_INVALID_DATA);
r_string = str;
- // Add padding
+ // Add padding.
strlen += pad;
- // Update buffer pos, left data count, and return size
+ // Update buffer pos, left data count, and return size.
buf += strlen;
len -= strlen;
if (r_len) {
@@ -111,6 +130,65 @@ static Error _decode_string(const uint8_t *&buf, int &len, int *r_len, String &r
return OK;
}
+static Error _decode_container_type(const uint8_t *&buf, int &len, int *r_len, bool p_allow_objects, ContainerTypeKind p_type_kind, ContainerType &r_type) {
+ switch (p_type_kind) {
+ case CONTAINER_TYPE_KIND_NONE: {
+ return OK;
+ } break;
+ case CONTAINER_TYPE_KIND_BUILTIN: {
+ ERR_FAIL_COND_V(len < 4, ERR_INVALID_DATA);
+
+ int32_t bt = decode_uint32(buf);
+ buf += 4;
+ len -= 4;
+ if (r_len) {
+ (*r_len) += 4;
+ }
+
+ ERR_FAIL_INDEX_V(bt, Variant::VARIANT_MAX, ERR_INVALID_DATA);
+ r_type.builtin_type = (Variant::Type)bt;
+ if (!p_allow_objects && r_type.builtin_type == Variant::OBJECT) {
+ r_type.class_name = EncodedObjectAsID::get_class_static();
+ }
+ return OK;
+ } break;
+ case CONTAINER_TYPE_KIND_CLASS_NAME: {
+ String str;
+ Error err = _decode_string(buf, len, r_len, str);
+ if (err) {
+ return err;
+ }
+
+ r_type.builtin_type = Variant::OBJECT;
+ if (p_allow_objects) {
+ r_type.class_name = str;
+ } else {
+ r_type.class_name = EncodedObjectAsID::get_class_static();
+ }
+ return OK;
+ } break;
+ case CONTAINER_TYPE_KIND_SCRIPT: {
+ String path;
+ Error err = _decode_string(buf, len, r_len, path);
+ if (err) {
+ return err;
+ }
+
+ r_type.builtin_type = Variant::OBJECT;
+ if (p_allow_objects) {
+ ERR_FAIL_COND_V_MSG(path.is_empty() || !path.begins_with("res://") || !ResourceLoader::exists(path, "Script"), ERR_INVALID_DATA, vformat("Invalid script path \"%s\".", path));
+ r_type.script = ResourceLoader::load(path, "Script");
+ ERR_FAIL_COND_V_MSG(r_type.script.is_null(), ERR_INVALID_DATA, vformat("Can't load script at path \"%s\".", path));
+ r_type.class_name = r_type.script->get_instance_base_type();
+ } else {
+ r_type.class_name = EncodedObjectAsID::get_class_static();
+ }
+ return OK;
+ } break;
+ }
+ ERR_FAIL_V_MSG(ERR_INVALID_DATA, "Invalid container type kind."); // Future proofing.
+}
+
Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int *r_len, bool p_allow_objects, int p_depth) {
ERR_FAIL_COND_V_MSG(p_depth > Variant::MAX_RECURSION_DEPTH, ERR_OUT_OF_MEMORY, "Variant is too deep. Bailing.");
const uint8_t *buf = p_buffer;
@@ -128,7 +206,7 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int
*r_len = 4;
}
- // Note: We cannot use sizeof(real_t) for decoding, in case a different size is encoded.
+ // NOTE: We cannot use `sizeof(real_t)` for decoding, in case a different size is encoded.
// Decoding math types always checks for the encoded size, while encoding always uses compilation setting.
// This does lead to some code duplication for decoding, but compatibility is the priority.
switch (header & HEADER_TYPE_MASK) {
@@ -190,7 +268,7 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int
} break;
- // math types
+ // Math types.
case Variant::VECTOR2: {
Vector2 val;
if (header & HEADER_DATA_FLAG_64) {
@@ -541,7 +619,8 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int
r_variant = val;
} break;
- // misc types
+
+ // Misc types.
case Variant::COLOR: {
ERR_FAIL_COND_V(len < 4 * 4, ERR_INVALID_DATA);
Color val;
@@ -570,7 +649,7 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int
int32_t strlen = decode_uint32(buf);
if (strlen & 0x80000000) {
- //new format
+ // New format.
ERR_FAIL_COND_V(len < 12, ERR_INVALID_DATA);
Vector<StringName> names;
Vector<StringName> subnames;
@@ -609,8 +688,7 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int
r_variant = NodePath(names, subnames, np_flags & 1);
} else {
- //old format, just a string
-
+ // Old format, just a string.
ERR_FAIL_V(ERR_INVALID_DATA);
}
@@ -700,9 +778,9 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int
if (str == "script" && value.get_type() != Variant::NIL) {
ERR_FAIL_COND_V_MSG(value.get_type() != Variant::STRING, ERR_INVALID_DATA, "Invalid value for \"script\" property, expected script path as String.");
String path = value;
- ERR_FAIL_COND_V_MSG(path.is_empty() || !path.begins_with("res://") || !ResourceLoader::exists(path, "Script"), ERR_INVALID_DATA, vformat("Invalid script path: '%s'.", path));
+ ERR_FAIL_COND_V_MSG(path.is_empty() || !path.begins_with("res://") || !ResourceLoader::exists(path, "Script"), ERR_INVALID_DATA, vformat("Invalid script path \"%s\".", path));
Ref<Script> script = ResourceLoader::load(path, "Script");
- ERR_FAIL_COND_V_MSG(script.is_null(), ERR_INVALID_DATA, vformat("Can't load script at path: '%s'.", path));
+ ERR_FAIL_COND_V_MSG(script.is_null(), ERR_INVALID_DATA, vformat("Can't load script at path \"%s\".", path));
obj->set_script(script);
} else {
obj->set(str, value);
@@ -733,9 +811,30 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int
r_variant = Signal(id, StringName(name));
} break;
case Variant::DICTIONARY: {
+ ContainerType key_type;
+
+ {
+ ContainerTypeKind key_type_kind = GET_CONTAINER_TYPE_KIND(header, TYPED_DICTIONARY_KEY);
+ Error err = _decode_container_type(buf, len, r_len, p_allow_objects, key_type_kind, key_type);
+ if (err) {
+ return err;
+ }
+ }
+
+ ContainerType value_type;
+
+ {
+ ContainerTypeKind value_type_kind = GET_CONTAINER_TYPE_KIND(header, TYPED_DICTIONARY_VALUE);
+ Error err = _decode_container_type(buf, len, r_len, p_allow_objects, value_type_kind, value_type);
+ if (err) {
+ return err;
+ }
+ }
+
ERR_FAIL_COND_V(len < 4, ERR_INVALID_DATA);
+
int32_t count = decode_uint32(buf);
- // bool shared = count&0x80000000;
+ //bool shared = count & 0x80000000;
count &= 0x7FFFFFFF;
buf += 4;
@@ -745,7 +844,10 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int
(*r_len) += 4; // Size of count number.
}
- Dictionary d;
+ Dictionary dict;
+ if (key_type.builtin_type != Variant::NIL || value_type.builtin_type != Variant::NIL) {
+ dict.set_typed(key_type.builtin_type, key_type.class_name, key_type.script, value_type.builtin_type, value_type.class_name, value_type.script);
+ }
for (int i = 0; i < count; i++) {
Variant key, value;
@@ -769,75 +871,27 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int
(*r_len) += used;
}
- d[key] = value;
+ dict[key] = value;
}
- r_variant = d;
+ r_variant = dict;
} break;
case Variant::ARRAY: {
- Variant::Type builtin_type = Variant::VARIANT_MAX;
- StringName class_name;
- Ref<Script> script;
-
- switch (header & HEADER_DATA_FIELD_TYPED_ARRAY_MASK) {
- case HEADER_DATA_FIELD_TYPED_ARRAY_NONE:
- break; // Untyped array.
- case HEADER_DATA_FIELD_TYPED_ARRAY_BUILTIN: {
- ERR_FAIL_COND_V(len < 4, ERR_INVALID_DATA);
-
- int32_t bt = decode_uint32(buf);
- buf += 4;
- len -= 4;
- if (r_len) {
- (*r_len) += 4;
- }
+ ContainerType type;
- ERR_FAIL_INDEX_V(bt, Variant::VARIANT_MAX, ERR_INVALID_DATA);
- builtin_type = (Variant::Type)bt;
- if (!p_allow_objects && builtin_type == Variant::OBJECT) {
- class_name = EncodedObjectAsID::get_class_static();
- }
- } break;
- case HEADER_DATA_FIELD_TYPED_ARRAY_CLASS_NAME: {
- String str;
- Error err = _decode_string(buf, len, r_len, str);
- if (err) {
- return err;
- }
-
- builtin_type = Variant::OBJECT;
- if (p_allow_objects) {
- class_name = str;
- } else {
- class_name = EncodedObjectAsID::get_class_static();
- }
- } break;
- case HEADER_DATA_FIELD_TYPED_ARRAY_SCRIPT: {
- String path;
- Error err = _decode_string(buf, len, r_len, path);
- if (err) {
- return err;
- }
-
- builtin_type = Variant::OBJECT;
- if (p_allow_objects) {
- ERR_FAIL_COND_V_MSG(path.is_empty() || !path.begins_with("res://") || !ResourceLoader::exists(path, "Script"), ERR_INVALID_DATA, vformat("Invalid script path: '%s'.", path));
- script = ResourceLoader::load(path, "Script");
- ERR_FAIL_COND_V_MSG(script.is_null(), ERR_INVALID_DATA, vformat("Can't load script at path: '%s'.", path));
- class_name = script->get_instance_base_type();
- } else {
- class_name = EncodedObjectAsID::get_class_static();
- }
- } break;
- default:
- ERR_FAIL_V(ERR_INVALID_DATA); // Future proofing.
+ {
+ ContainerTypeKind type_kind = GET_CONTAINER_TYPE_KIND(header, TYPED_ARRAY);
+ Error err = _decode_container_type(buf, len, r_len, p_allow_objects, type_kind, type);
+ if (err) {
+ return err;
+ }
}
ERR_FAIL_COND_V(len < 4, ERR_INVALID_DATA);
int32_t count = decode_uint32(buf);
- // bool shared = count&0x80000000;
+ //bool shared = count & 0x80000000;
count &= 0x7FFFFFFF;
buf += 4;
@@ -847,29 +901,29 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int
(*r_len) += 4; // Size of count number.
}
- Array varr;
- if (builtin_type != Variant::VARIANT_MAX) {
- varr.set_typed(builtin_type, class_name, script);
+ Array array;
+ if (type.builtin_type != Variant::NIL) {
+ array.set_typed(type.builtin_type, type.class_name, type.script);
}
for (int i = 0; i < count; i++) {
int used = 0;
- Variant v;
- Error err = decode_variant(v, buf, len, &used, p_allow_objects, p_depth + 1);
+ Variant elem;
+ Error err = decode_variant(elem, buf, len, &used, p_allow_objects, p_depth + 1);
ERR_FAIL_COND_V_MSG(err != OK, err, "Error when trying to decode Variant.");
buf += used;
len -= used;
- varr.push_back(v);
+ array.push_back(elem);
if (r_len) {
(*r_len) += used;
}
}
- r_variant = varr;
+ r_variant = array;
} break;
- // arrays
+ // Packed arrays.
case Variant::PACKED_BYTE_ARRAY: {
ERR_FAIL_COND_V(len < 4, ERR_INVALID_DATA);
int32_t count = decode_uint32(buf);
@@ -908,7 +962,7 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int
Vector<int32_t> data;
if (count) {
- //const int*rbuf=(const int*)buf;
+ //const int *rbuf = (const int *)buf;
data.resize(count);
int32_t *w = data.ptrw();
for (int32_t i = 0; i < count; i++) {
@@ -932,7 +986,7 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int
Vector<int64_t> data;
if (count) {
- //const int*rbuf=(const int*)buf;
+ //const int *rbuf = (const int *)buf;
data.resize(count);
int64_t *w = data.ptrw();
for (int64_t i = 0; i < count; i++) {
@@ -956,7 +1010,7 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int
Vector<float> data;
if (count) {
- //const float*rbuf=(const float*)buf;
+ //const float *rbuf = (const float *)buf;
data.resize(count);
float *w = data.ptrw();
for (int32_t i = 0; i < count; i++) {
@@ -1267,13 +1321,50 @@ static void _encode_string(const String &p_string, uint8_t *&buf, int &r_len) {
r_len += 4 + utf8.length();
while (r_len % 4) {
- r_len++; //pad
+ r_len++; // Pad.
if (buf) {
*(buf++) = 0;
}
}
}
+static void _encode_container_type_header(const ContainerType &p_type, uint32_t &header, uint32_t p_shift, bool p_full_objects) {
+ if (p_type.builtin_type != Variant::NIL) {
+ if (p_type.script.is_valid()) {
+ header |= (p_full_objects ? CONTAINER_TYPE_KIND_SCRIPT : CONTAINER_TYPE_KIND_CLASS_NAME) << p_shift;
+ } else if (p_type.class_name != StringName()) {
+ header |= CONTAINER_TYPE_KIND_CLASS_NAME << p_shift;
+ } else {
+ // No need to check `p_full_objects` since `class_name` should be non-empty for `builtin_type == Variant::OBJECT`.
+ header |= CONTAINER_TYPE_KIND_BUILTIN << p_shift;
+ }
+ }
+}
+
+static Error _encode_container_type(const ContainerType &p_type, uint8_t *&buf, int &r_len, bool p_full_objects) {
+ if (p_type.builtin_type != Variant::NIL) {
+ if (p_type.script.is_valid()) {
+ if (p_full_objects) {
+ String path = p_type.script->get_path();
+ ERR_FAIL_COND_V_MSG(path.is_empty() || !path.begins_with("res://"), ERR_UNAVAILABLE, "Failed to encode a path to a custom script for a container type.");
+ _encode_string(path, buf, r_len);
+ } else {
+ _encode_string(EncodedObjectAsID::get_class_static(), buf, r_len);
+ }
+ } else if (p_type.class_name != StringName()) {
+ _encode_string(p_full_objects ? p_type.class_name.operator String() : EncodedObjectAsID::get_class_static(), buf, r_len);
+ } else {
+ // No need to check `p_full_objects` since `class_name` should be non-empty for `builtin_type == Variant::OBJECT`.
+ if (buf) {
+ encode_uint32(p_type.builtin_type, buf);
+ buf += 4;
+ }
+ r_len += 4;
+ }
+ }
+ return OK;
+}
+
Error encode_variant(const Variant &p_variant, uint8_t *r_buffer, int &r_len, bool p_full_objects, int p_depth) {
ERR_FAIL_COND_V_MSG(p_depth > Variant::MAX_RECURSION_DEPTH, ERR_OUT_OF_MEMORY, "Potential infinite recursion detected. Bailing.");
uint8_t *buf = r_buffer;
@@ -1312,20 +1403,32 @@ Error encode_variant(const Variant &p_variant, uint8_t *r_buffer, int &r_len, bo
header |= HEADER_DATA_FLAG_OBJECT_AS_ID;
}
} break;
+ case Variant::DICTIONARY: {
+ Dictionary dict = p_variant;
+
+ ContainerType key_type;
+ key_type.builtin_type = (Variant::Type)dict.get_typed_key_builtin();
+ key_type.class_name = dict.get_typed_key_class_name();
+ key_type.script = dict.get_typed_key_script();
+
+ _encode_container_type_header(key_type, header, HEADER_DATA_FIELD_TYPED_DICTIONARY_KEY_SHIFT, p_full_objects);
+
+ ContainerType value_type;
+ value_type.builtin_type = (Variant::Type)dict.get_typed_value_builtin();
+ value_type.class_name = dict.get_typed_value_class_name();
+ value_type.script = dict.get_typed_value_script();
+
+ _encode_container_type_header(value_type, header, HEADER_DATA_FIELD_TYPED_DICTIONARY_VALUE_SHIFT, p_full_objects);
+ } break;
case Variant::ARRAY: {
Array array = p_variant;
- if (array.is_typed()) {
- Ref<Script> script = array.get_typed_script();
- if (script.is_valid()) {
- header |= p_full_objects ? HEADER_DATA_FIELD_TYPED_ARRAY_SCRIPT : HEADER_DATA_FIELD_TYPED_ARRAY_CLASS_NAME;
- } else if (array.get_typed_class_name() != StringName()) {
- header |= HEADER_DATA_FIELD_TYPED_ARRAY_CLASS_NAME;
- } else {
- // No need to check `p_full_objects` since for `Variant::OBJECT`
- // `array.get_typed_class_name()` should be non-empty.
- header |= HEADER_DATA_FIELD_TYPED_ARRAY_BUILTIN;
- }
- }
+
+ ContainerType type;
+ type.builtin_type = (Variant::Type)array.get_typed_builtin();
+ type.class_name = array.get_typed_class_name();
+ type.script = array.get_typed_script();
+
+ _encode_container_type_header(type, header, HEADER_DATA_FIELD_TYPED_ARRAY_SHIFT, p_full_objects);
} break;
#ifdef REAL_T_IS_DOUBLE
case Variant::VECTOR2:
@@ -1346,7 +1449,8 @@ Error encode_variant(const Variant &p_variant, uint8_t *r_buffer, int &r_len, bo
} break;
#endif // REAL_T_IS_DOUBLE
default: {
- } // nothing to do at this stage
+ // Nothing to do at this stage.
+ } break;
}
if (buf) {
@@ -1357,7 +1461,7 @@ Error encode_variant(const Variant &p_variant, uint8_t *r_buffer, int &r_len, bo
switch (p_variant.get_type()) {
case Variant::NIL: {
- //nothing to do
+ // Nothing to do.
} break;
case Variant::BOOL: {
if (buf) {
@@ -1369,7 +1473,7 @@ Error encode_variant(const Variant &p_variant, uint8_t *r_buffer, int &r_len, bo
} break;
case Variant::INT: {
if (header & HEADER_DATA_FLAG_64) {
- //64 bits
+ // 64 bits.
if (buf) {
encode_uint64(p_variant.operator int64_t(), buf);
}
@@ -1403,7 +1507,7 @@ Error encode_variant(const Variant &p_variant, uint8_t *r_buffer, int &r_len, bo
case Variant::NODE_PATH: {
NodePath np = p_variant;
if (buf) {
- encode_uint32(uint32_t(np.get_name_count()) | 0x80000000, buf); //for compatibility with the old format
+ encode_uint32(uint32_t(np.get_name_count()) | 0x80000000, buf); // For compatibility with the old format.
encode_uint32(np.get_subname_count(), buf + 4);
uint32_t np_flags = 0;
if (np.is_absolute()) {
@@ -1453,7 +1557,7 @@ Error encode_variant(const Variant &p_variant, uint8_t *r_buffer, int &r_len, bo
} break;
- // math types
+ // Math types.
case Variant::VECTOR2: {
if (buf) {
Vector2 v2 = p_variant;
@@ -1637,7 +1741,7 @@ Error encode_variant(const Variant &p_variant, uint8_t *r_buffer, int &r_len, bo
} break;
- // misc types
+ // Misc types.
case Variant::COLOR: {
if (buf) {
Color c = p_variant;
@@ -1748,29 +1852,53 @@ Error encode_variant(const Variant &p_variant, uint8_t *r_buffer, int &r_len, bo
r_len += 8;
} break;
case Variant::DICTIONARY: {
- Dictionary d = p_variant;
+ Dictionary dict = p_variant;
+
+ {
+ ContainerType key_type;
+ key_type.builtin_type = (Variant::Type)dict.get_typed_key_builtin();
+ key_type.class_name = dict.get_typed_key_class_name();
+ key_type.script = dict.get_typed_key_script();
+
+ Error err = _encode_container_type(key_type, buf, r_len, p_full_objects);
+ if (err) {
+ return err;
+ }
+ }
+
+ {
+ ContainerType value_type;
+ value_type.builtin_type = (Variant::Type)dict.get_typed_value_builtin();
+ value_type.class_name = dict.get_typed_value_class_name();
+ value_type.script = dict.get_typed_value_script();
+
+ Error err = _encode_container_type(value_type, buf, r_len, p_full_objects);
+ if (err) {
+ return err;
+ }
+ }
if (buf) {
- encode_uint32(uint32_t(d.size()), buf);
+ encode_uint32(uint32_t(dict.size()), buf);
buf += 4;
}
r_len += 4;
List<Variant> keys;
- d.get_key_list(&keys);
+ dict.get_key_list(&keys);
- for (const Variant &E : keys) {
+ for (const Variant &key : keys) {
int len;
- Error err = encode_variant(E, buf, len, p_full_objects, p_depth + 1);
+ Error err = encode_variant(key, buf, len, p_full_objects, p_depth + 1);
ERR_FAIL_COND_V(err, err);
ERR_FAIL_COND_V(len % 4, ERR_BUG);
r_len += len;
if (buf) {
buf += len;
}
- Variant *v = d.getptr(E);
- ERR_FAIL_NULL_V(v, ERR_BUG);
- err = encode_variant(*v, buf, len, p_full_objects, p_depth + 1);
+ Variant *value = dict.getptr(key);
+ ERR_FAIL_NULL_V(value, ERR_BUG);
+ err = encode_variant(*value, buf, len, p_full_objects, p_depth + 1);
ERR_FAIL_COND_V(err, err);
ERR_FAIL_COND_V(len % 4, ERR_BUG);
r_len += len;
@@ -1783,27 +1911,15 @@ Error encode_variant(const Variant &p_variant, uint8_t *r_buffer, int &r_len, bo
case Variant::ARRAY: {
Array array = p_variant;
- if (array.is_typed()) {
- Variant variant = array.get_typed_script();
- Ref<Script> script = variant;
- if (script.is_valid()) {
- if (p_full_objects) {
- String path = script->get_path();
- ERR_FAIL_COND_V_MSG(path.is_empty() || !path.begins_with("res://"), ERR_UNAVAILABLE, "Failed to encode a path to a custom script for an array type.");
- _encode_string(path, buf, r_len);
- } else {
- _encode_string(EncodedObjectAsID::get_class_static(), buf, r_len);
- }
- } else if (array.get_typed_class_name() != StringName()) {
- _encode_string(p_full_objects ? array.get_typed_class_name().operator String() : EncodedObjectAsID::get_class_static(), buf, r_len);
- } else {
- // No need to check `p_full_objects` since for `Variant::OBJECT`
- // `array.get_typed_class_name()` should be non-empty.
- if (buf) {
- encode_uint32(array.get_typed_builtin(), buf);
- buf += 4;
- }
- r_len += 4;
+ {
+ ContainerType type;
+ type.builtin_type = (Variant::Type)array.get_typed_builtin();
+ type.class_name = array.get_typed_class_name();
+ type.script = array.get_typed_script();
+
+ Error err = _encode_container_type(type, buf, r_len, p_full_objects);
+ if (err) {
+ return err;
}
}
@@ -1813,9 +1929,9 @@ Error encode_variant(const Variant &p_variant, uint8_t *r_buffer, int &r_len, bo
}
r_len += 4;
- for (const Variant &var : array) {
+ for (const Variant &elem : array) {
int len;
- Error err = encode_variant(var, buf, len, p_full_objects, p_depth + 1);
+ Error err = encode_variant(elem, buf, len, p_full_objects, p_depth + 1);
ERR_FAIL_COND_V(err, err);
ERR_FAIL_COND_V(len % 4, ERR_BUG);
if (buf) {
@@ -1825,7 +1941,8 @@ Error encode_variant(const Variant &p_variant, uint8_t *r_buffer, int &r_len, bo
}
} break;
- // arrays
+
+ // Packed arrays.
case Variant::PACKED_BYTE_ARRAY: {
Vector<uint8_t> data = p_variant;
int datalen = data.size();
@@ -1941,7 +2058,7 @@ Error encode_variant(const Variant &p_variant, uint8_t *r_buffer, int &r_len, bo
r_len += 4 + utf8.length() + 1;
while (r_len % 4) {
- r_len++; //pad
+ r_len++; // Pad.
if (buf) {
*(buf++) = 0;
}
@@ -2059,9 +2176,9 @@ Error encode_variant(const Variant &p_variant, uint8_t *r_buffer, int &r_len, bo
}
Vector<float> vector3_to_float32_array(const Vector3 *vecs, size_t count) {
- // We always allocate a new array, and we don't memcpy.
- // We also don't consider returning a pointer to the passed vectors when sizeof(real_t) == 4.
- // One reason is that we could decide to put a 4th component in Vector3 for SIMD/mobile performance,
+ // We always allocate a new array, and we don't `memcpy()`.
+ // We also don't consider returning a pointer to the passed vectors when `sizeof(real_t) == 4`.
+ // One reason is that we could decide to put a 4th component in `Vector3` for SIMD/mobile performance,
// which would cause trouble with these optimizations.
Vector<float> floats;
if (count == 0) {