Skip to content

Commit aeca1b9

Browse files
thijsmieeboasson
authored andcommitted
Set supported data_representations for type, add recursive scan on typetree to determine it.
1 parent d1f9877 commit aeca1b9

File tree

13 files changed

+219
-80
lines changed

13 files changed

+219
-80
lines changed

clayer/pysertype.c

Lines changed: 36 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -795,7 +795,7 @@ static bool valid_pt_or_set_error(void *py_obj)
795795
static ddspy_sertype_t *ddspy_sertype_new(PyObject *pytype)
796796
{
797797
// PyObjects
798-
PyObject *idl = NULL, *pyname = NULL, *pykeyless = NULL, *pyxcdrv2 = NULL, *v0pykeysize = NULL, *v2pykeysize = NULL;
798+
PyObject *idl = NULL, *pyname = NULL, *pykeyless = NULL, *pyversion_support = NULL, *v0pykeysize = NULL, *v2pykeysize = NULL;
799799
#ifdef DDS_HAS_TYPE_DISCOVERY
800800
PyObject *xt_type_data = NULL;
801801
Py_buffer xt_type_map_bytes, xt_type_info_bytes;
@@ -815,8 +815,8 @@ static ddspy_sertype_t *ddspy_sertype_new(PyObject *pytype)
815815
pykeyless = PyObject_GetAttrString(idl, "keyless");
816816
if (!valid_topic_py_or_set_error(pykeyless)) goto err;
817817

818-
pyxcdrv2 = PyObject_GetAttrString(idl, "xcdrv2");
819-
if (!valid_topic_py_or_set_error(pyxcdrv2)) goto err;
818+
pyversion_support = PyObject_GetAttrString(idl, "version_support");
819+
if (!valid_topic_py_or_set_error(pyversion_support)) goto err;
820820

821821
#ifdef DDS_HAS_TYPE_DISCOVERY
822822
xt_type_data = PyObject_GetAttrString(idl, "_xt_bytedata");
@@ -833,7 +833,7 @@ static ddspy_sertype_t *ddspy_sertype_new(PyObject *pytype)
833833
Py_INCREF(pytype);
834834
new->my_py_type = pytype;
835835
new->keyless = keyless;
836-
new->is_v2_by_default = pyxcdrv2 == Py_True;
836+
new->is_v2_by_default = PyLong_AsLong(pyversion_support) == 2; // XCDRSupported.SupportsBasic = 1, SupportsV2 = 2
837837

838838
#ifdef DDS_HAS_TYPE_DISCOVERY
839839
if (xt_type_data != Py_None && PyTuple_GetItem(xt_type_data, 0) != Py_None) {
@@ -881,20 +881,36 @@ static ddspy_sertype_t *ddspy_sertype_new(PyObject *pytype)
881881
#endif
882882

883883
if (!keyless) {
884-
new->v0_key_vm = make_key_vm(idl, false);
885-
if (!valid_pt_or_set_error(new->v0_key_vm)) goto err;
886884
new->v2_key_vm = make_key_vm(idl, true);
887885
if (!valid_pt_or_set_error(new->v2_key_vm)) goto err;
888886

889887
v0pykeysize = PyObject_GetAttrString(idl, "v0_key_max_size");
890-
if (!valid_topic_py_or_set_error(v0pykeysize)) goto err;
891-
v2pykeysize = PyObject_GetAttrString(idl, "v2_key_max_size");
892-
if (!valid_topic_py_or_set_error(v2pykeysize)) goto err;
888+
if (!valid_topic_py_or_set_error(v0pykeysize)) {
889+
// No support for v0
890+
if ((PyLong_AsLong(pyversion_support) & 1) > 0)
891+
goto err;
892+
new->v0_key_vm = NULL;
893+
new->v0_key_maxsize_bigger_16 = false;
894+
} else {
895+
new->v0_key_vm = make_key_vm(idl, false);
896+
if (!valid_pt_or_set_error(new->v0_key_vm)) goto err;
897+
long long v0keysize = PyLong_AsLongLong(v0pykeysize);
898+
new->v0_key_maxsize_bigger_16 = v0keysize > 16;
899+
}
893900

894-
long long v0keysize = PyLong_AsLongLong(v0pykeysize);
895-
new->v0_key_maxsize_bigger_16 = v0keysize > 16;
896-
long long v2keysize = PyLong_AsLongLong(v2pykeysize);
897-
new->v2_key_maxsize_bigger_16 = v2keysize > 16;
901+
v2pykeysize = PyObject_GetAttrString(idl, "v2_key_max_size");
902+
if (!valid_topic_py_or_set_error(v2pykeysize)) {
903+
// No support for v0
904+
if ((PyLong_AsLong(pyversion_support) & 2) > 0)
905+
goto err;
906+
new->v2_key_vm = NULL;
907+
new->v2_key_maxsize_bigger_16 = false;
908+
} else {
909+
new->v2_key_vm = make_key_vm(idl, true);
910+
if (!valid_pt_or_set_error(new->v2_key_vm)) goto err;
911+
long long v2keysize = PyLong_AsLongLong(v2pykeysize);
912+
new->v2_key_maxsize_bigger_16 = v2keysize > 16;
913+
}
898914
} else {
899915
new->v0_key_vm = NULL;
900916
new->v0_key_maxsize_bigger_16 = true;
@@ -909,6 +925,12 @@ static ddspy_sertype_t *ddspy_sertype_new(PyObject *pytype)
909925
&ddspy_serdata_ops,
910926
keyless
911927
);
928+
929+
if (new->is_v2_by_default)
930+
new->my_c_type.allowed_data_representation = DDS_DATA_REPRESENTATION_FLAG_XCDR2;
931+
else
932+
new->my_c_type.allowed_data_representation = DDS_DATA_REPRESENTATION_FLAG_XCDR1 | DDS_DATA_REPRESENTATION_FLAG_XCDR2;
933+
912934
constructed = true;
913935

914936
err:
@@ -921,7 +943,7 @@ static ddspy_sertype_t *ddspy_sertype_new(PyObject *pytype)
921943
Py_XDECREF(idl);
922944
Py_XDECREF(pyname);
923945
Py_XDECREF(pykeyless);
924-
Py_XDECREF(pyxcdrv2);
946+
Py_XDECREF(pyversion_support);
925947
Py_XDECREF(v0pykeysize);
926948
Py_XDECREF(v2pykeysize);
927949

cyclonedds/builtin.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,7 @@ def endpoint_constructor(keybytes, participant_keybytes, p_instance_handle, topi
147147
ident = None
148148
if typeid_bytes is not None:
149149
try:
150-
ident = TypeIdentifier.deserialize(typeid_bytes, has_header=False)
150+
ident = TypeIdentifier.deserialize(typeid_bytes, has_header=False, use_version_2=True)
151151
except Exception:
152152
pass
153153

cyclonedds/dynamic.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ def get_types_for_typeid(participant: DomainParticipant, type_id: TypeIdentifier
4545
raise DDSException(ret, f"Could not fetch typeobject for {tid}")
4646

4747
try:
48-
type_object = TypeObject.deserialize(ret, has_header=False)
48+
type_object = TypeObject.deserialize(ret, has_header=False, use_version_2=True)
4949
except Exception as e:
5050
raise DDSException(DDSException.DDS_RETCODE_ERROR, "Got invalid TypeObject from C layer.") from e
5151

cyclonedds/idl/__init__.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -25,12 +25,12 @@
2525

2626

2727
class IdlStruct(metaclass=IdlMeta):
28-
def serialize(self, buffer: Optional[Buffer] = None, endianness: Optional[Endianness] = None, use_version_2: bool = None) -> bytes:
28+
def serialize(self, buffer: Optional[Buffer] = None, endianness: Optional[Endianness] = None, use_version_2: Optional[bool] = None) -> bytes:
2929
return self.__idl__.serialize(self, buffer=buffer, endianness=endianness, use_version_2=use_version_2)
3030

3131
@classmethod
32-
def deserialize(cls: Type[_TIS], data: bytes, has_header: bool = True) -> _TIS:
33-
return cls.__idl__.deserialize(data, has_header=has_header)
32+
def deserialize(cls: Type[_TIS], data: bytes, has_header: bool = True, use_version_2: Optional[bool] = None) -> _TIS:
33+
return cls.__idl__.deserialize(data, has_header=has_header, use_version_2=use_version_2)
3434

3535

3636
def make_idl_struct(class_name: str, typename: str, fields: Dict[str, Any], *, dataclassify=True,
@@ -157,12 +157,12 @@ def __eq__(self, other):
157157
return False
158158
return True
159159

160-
def serialize(self, buffer: Optional[Buffer] = None, endianness: Optional[Endianness] = None, use_version_2: bool = None) -> bytes:
160+
def serialize(self, buffer: Optional[Buffer] = None, endianness: Optional[Endianness] = None, use_version_2: Optional[bool] = None) -> bytes:
161161
return self.__idl__.serialize(self, buffer=buffer, endianness=endianness, use_version_2=use_version_2)
162162

163163
@classmethod
164-
def deserialize(cls: Type[_TIU], data: bytes, has_header: bool = True) -> _TIU:
165-
return cls.__idl__.deserialize(data, has_header=has_header)
164+
def deserialize(cls: Type[_TIU], data: bytes, has_header: bool = True, use_version_2: Optional[bool] = None) -> _TIU:
165+
return cls.__idl__.deserialize(data, has_header=has_header, use_version_2=use_version_2)
166166

167167

168168
def make_idl_union(class_name: str, typename: str, fields: Dict[str, ValidUnionHolder],

cyclonedds/idl/_builder.py

Lines changed: 72 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
1111
"""
1212

13-
from enum import Enum
13+
from enum import Enum, IntFlag, auto
1414
from inspect import isclass
1515
from typing import Tuple, Type, Union
1616

@@ -26,6 +26,12 @@
2626
case, default
2727

2828

29+
class XCDRSupported(IntFlag):
30+
SupportsBasic = 1
31+
SupportsV2 = 2
32+
SupportsBoth = SupportsBasic | SupportsV2
33+
34+
2935
class Builder:
3036
easy_types = {
3137
char: CharMachine,
@@ -36,6 +42,70 @@ class Builder:
3642
None: NoneMachine
3743
}
3844

45+
@classmethod
46+
def _scan_for_support(cls, _type, done) -> XCDRSupported:
47+
if id(_type) in done:
48+
return XCDRSupported.SupportsBoth
49+
# to avoid infinite recursing. Since this is the 'all' flag it
50+
# will not affect the result, because of the tree structure it is
51+
# guaranteed to be binary and'ed with the real result.
52+
done.add(id(_type))
53+
54+
if isinstance(_type, WrapOpt):
55+
return XCDRSupported.SupportsV2
56+
elif isinstance(_type, (typedef, sequence, array)):
57+
return cls._scan_for_support(_type.subtype, done)
58+
elif get_origin(_type) == list:
59+
return cls._scan_for_support(get_args(_type)[0], done)
60+
elif get_origin(_type) == dict:
61+
return cls._scan_for_support(get_args(_type)[0], done) & cls._scan_for_support(get_args(_type)[1], done)
62+
elif isclass(_type) and issubclass(_type, IdlStruct):
63+
fields = get_extended_type_hints(_type)
64+
annotations = get_idl_annotations(_type)
65+
66+
# Explicit setter
67+
if 'xcdrv2' in annotations:
68+
if annotations['xcdrv2']:
69+
return XCDRSupported.SupportsV2
70+
else:
71+
return XCDRSupported.SupportsBasic
72+
73+
# Appendable and mutable is definitely V2
74+
if 'extensibility' in annotations:
75+
if annotations['extensibility'] in ['appendable', 'mutable']:
76+
return XCDRSupported.SupportsV2
77+
78+
# Check for optionals or nested mutable/appendable
79+
support = XCDRSupported.SupportsBoth
80+
for _, _ftype in fields.items():
81+
support &= cls._scan_for_support(_ftype, done)
82+
83+
return support
84+
elif isclass(_type) and issubclass(_type, IdlUnion):
85+
fields = get_extended_type_hints(_type)
86+
annotations = get_idl_annotations(_type)
87+
88+
# Explicit setter
89+
if 'xcdrv2' in annotations:
90+
if annotations['xcdrv2']:
91+
return XCDRSupported.SupportsV2
92+
else:
93+
return XCDRSupported.SupportsBasic
94+
95+
# Appendable and mutable is definitely V2
96+
if 'extensibility' in annotations:
97+
if annotations['extensibility'] in ['appendable', 'mutable']:
98+
return XCDRSupported.SupportsV2
99+
100+
# Check for optionals or nested mutable/appendable
101+
support = XCDRSupported.SupportsBoth
102+
for _, _ftype in fields.items():
103+
support &= cls._scan_for_support(_ftype.subtype, done)
104+
105+
return support
106+
return XCDRSupported.SupportsBoth
107+
108+
39109
@classmethod
40110
def _machine_for_type(cls, _type, add_size_header, use_version_2):
41111
if _type in cls.easy_types:
@@ -242,4 +312,4 @@ def build_machines(cls, _type):
242312
else:
243313
raise Exception(f"Cannot build for {_type}, not struct or union.")
244314

245-
return v0_machine, v2_machine, keyless
315+
return v0_machine, v2_machine, keyless, cls._scan_for_support(_type, set())

0 commit comments

Comments
 (0)