-
-
Notifications
You must be signed in to change notification settings - Fork 21.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Make inst_to_dict
and dict_to_inst
recursive
#97244
base: master
Are you sure you want to change the base?
Conversation
Please pay special attention to my poorly attempt to document the changes that I did to |
inst_to_dict
and dict_to_inst
recursive
e77f3af
to
59b04fc
Compare
inst_to_dict
and dict_to_inst
recursiveinst_to_dict
and dict_to_inst
recursive
59b04fc
to
f816784
Compare
8770516
to
5acece9
Compare
If I recall correctly, methods like |
@dalexeev I addressed your comment |
5acece9
to
f1f96e9
Compare
Friendly remainder |
Fixes godotengine#6533 Making GDScript inst_to_dict/dict_to_inst utility functions recursive. Adding also a new macro to validate the number of the required arguments and another to validate that an argument is boolean.
f1f96e9
to
153b526
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry for the long delay. I left a few comments, but they don't need to be fixed. I have doubts about whether we should make inst_to_dict()
and dict_to_inst()
recursive. Perhaps we should deprecate these functions instead. Let me explain why.
- You implemented recursive representation only for object properties, but nested objects can also be array elements and dictionary keys/values.
- Arrays and dictionaries can be typed, so they also need to be represented in a special way (say, as
{"@type": "Array", "@elem_builtin_type": "int", "@elements": [1, 2, 3]}
). Because we can't, for example, put a dictionary representation of an object into anArray[Object]
. - Arrays, dictionaries, and objects are passed by reference. Currently,
inst_to_dict()
creates a shallow copy, and all reference types in the dictionary representation are the same values as in the original object (see example below). If we make a deep version ofinst_to_dict()
, it would probably have to create duplicates, because of p. 2. This would be inconsistent with the flat version, which is essentially a separate serialization function with different behavior, hidden ininst_to_dict()
behind an optional parameter. - We already have other serialization functions:
var_to_bytes()
,var_to_str()
, and the new JSON functionality (see Ability to convert native engine types to JSON and back. #92656). I think 4 types of serialization is too many.var_to_str()
has security concerns, but it seems like the new JSON methods are aimed at being more secure (at least they have appropriate parameters). I think we should focus on the core serialization methods and deprecate the GDScript specificinst_to_dict()
anddict_to_inst()
functions.
class Test:
var a = []
func _ready():
var test = Test.new()
var dict = inst_to_dict(test)
print(dict) # { "@subpath": ^"Test", "@path": "res://node.gd", &"a": [] }
print(test.a) # []
dict.a.append(1)
print(dict) # { "@subpath": ^"Test", "@path": "res://node.gd", &"a": [1] }
print(test.a) # [1]
DEBUG_VALIDATE_ARG_COUNT(1, 1); | ||
DEBUG_VALIDATE_ARG_TYPE(0, Variant::DICTIONARY); | ||
static inline void inst_to_dict(Variant *r_ret, const Variant **p_args, int p_arg_count, Callable::CallError &r_error) { | ||
DEBUG_VALIDATE_ARG_COUNT(1, 2); | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks like you accidentally deleted DEBUG_VALIDATE_ARG_TYPE(0, Variant::OBJECT);
and DEBUG_VALIDATE_ARG_TYPE(0, Variant::DICTIONARY);
when rebasing the PR.
Variant member = inst->members[E.value.index]; | ||
if (p_deep && member.get_type() == Variant::OBJECT) { | ||
Variant inner_dict; | ||
_inst_to_dict(&inner_dict, &member, p_deep, ++p_recursion_count, r_error); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
++p_recursion_count
increases on each element, should be p_recursion_count + 1
.
if (unlikely(!Variant::can_convert_strict(p_var->get_type(), Variant::OBJECT))) { | ||
*r_ret = Variant(); | ||
r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT; | ||
r_error.argument = 0; | ||
r_error.expected = Variant::OBJECT; | ||
return; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can use VALIDATE_ARG_CUSTOM
or GDFUNC_FAIL_COND_MSG
.
Fixes #6533
Making GDScript inst_to_dict/dict_to_inst utility functions recursive.
Adding also a new macro to validate the number of the required arguments.