lib: have dedicated "dynamic array FC with/without length field" types
[babeltrace.git] / src / bindings / python / bt2 / bt2 / field.py
CommitLineData
81447b5b
PP
1# The MIT License (MIT)
2#
f6a5e476 3# Copyright (c) 2017 Philippe Proulx <pproulx@efficios.com>
81447b5b
PP
4#
5# Permission is hereby granted, free of charge, to any person obtaining a copy
6# of this software and associated documentation files (the "Software"), to deal
7# in the Software without restriction, including without limitation the rights
8# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9# copies of the Software, and to permit persons to whom the Software is
10# furnished to do so, subject to the following conditions:
11#
12# The above copyright notice and this permission notice shall be included in
13# all copies or substantial portions of the Software.
14#
15# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21# THE SOFTWARE.
22
23from bt2 import native_bt, object, utils
c946c9de 24from bt2 import field_class as bt2_field_class
81447b5b
PP
25import collections.abc
26import functools
27import numbers
28import math
81447b5b
PP
29
30
9cbe0c59
FD
31def _create_field_from_ptr_template(
32 object_map, ptr, owner_ptr, owner_get_ref, owner_put_ref
33):
34
27d97a3f 35 field_class_ptr = native_bt.field_borrow_class_const(ptr)
27d97a3f 36 typeid = native_bt.field_class_get_type(field_class_ptr)
9cbe0c59 37 field = object_map[typeid]._create_from_ptr_and_get_ref(
61d96b89
FD
38 ptr, owner_ptr, owner_get_ref, owner_put_ref
39 )
81447b5b
PP
40 return field
41
42
9cbe0c59
FD
43def _create_field_from_ptr(ptr, owner_ptr, owner_get_ref, owner_put_ref):
44 return _create_field_from_ptr_template(
45 _TYPE_ID_TO_OBJ, ptr, owner_ptr, owner_get_ref, owner_put_ref
46 )
47
48
49def _create_field_from_const_ptr(ptr, owner_ptr, owner_get_ref, owner_put_ref):
50 return _create_field_from_ptr_template(
51 _TYPE_ID_TO_CONST_OBJ, ptr, owner_ptr, owner_get_ref, owner_put_ref
52 )
53
54
84eba0d9
PP
55# Get the "effective" field of `field`. If `field` is a variant, return
56# the currently selected field. If `field` is an option, return the
57# content field. If `field` is of any other type, return `field`
4470d3a6 58# directly.
81447b5b 59
61d96b89 60
4470d3a6 61def _get_leaf_field(field):
9cbe0c59 62 if isinstance(field, _VariantFieldConst):
84eba0d9 63 return _get_leaf_field(field.selected_option)
4470d3a6 64
9cbe0c59 65 if isinstance(field, _OptionFieldConst):
84eba0d9
PP
66 return _get_leaf_field(field.field)
67
68 return field
81447b5b 69
80d037bc 70
9cbe0c59
FD
71class _FieldConst(object._UniqueObject):
72 _create_field_from_ptr = staticmethod(_create_field_from_const_ptr)
73 _create_field_class_from_ptr_and_get_ref = staticmethod(
74 bt2_field_class._create_field_class_from_const_ptr_and_get_ref
75 )
76 _borrow_class_ptr = staticmethod(native_bt.field_borrow_class_const)
77
4470d3a6 78 def __eq__(self, other):
80d037bc
JG
79 other = _get_leaf_field(other)
80 return self._spec_eq(other)
81
81447b5b 82 @property
ffe40722 83 def cls(self):
9cbe0c59 84 field_class_ptr = self._borrow_class_ptr(self._ptr)
e8d2391b 85 assert field_class_ptr is not None
9cbe0c59 86 return self._create_field_class_from_ptr_and_get_ref(field_class_ptr)
81447b5b 87
dc78ca2f
JG
88 def _repr(self):
89 raise NotImplementedError
90
91 def __repr__(self):
4470d3a6 92 return self._repr()
dc78ca2f 93
81447b5b 94
9cbe0c59
FD
95class _Field(_FieldConst):
96 _create_field_from_ptr = staticmethod(_create_field_from_ptr)
97 _create_field_class_from_ptr_and_get_ref = staticmethod(
98 bt2_field_class._create_field_class_from_ptr_and_get_ref
99 )
100 _borrow_class_ptr = staticmethod(native_bt.field_borrow_class)
101
102
103class _BitArrayFieldConst(_FieldConst):
104 _NAME = 'Const bit array'
6b29f2d4
PP
105
106 @property
107 def value_as_integer(self):
108 return native_bt.field_bit_array_get_value_as_integer(self._ptr)
109
6b29f2d4
PP
110 def _spec_eq(self, other):
111 if type(other) is not type(self):
112 return False
113
114 return self.value_as_integer == other.value_as_integer
115
116 def _repr(self):
117 return repr(self.value_as_integer)
118
119 def __str__(self):
120 return str(self.value_as_integer)
121
122 def __len__(self):
ffe40722 123 return self.cls.length
6b29f2d4
PP
124
125
9cbe0c59
FD
126class _BitArrayField(_BitArrayFieldConst, _Field):
127 _NAME = 'Bit array'
128
129 def _value_as_integer(self, value):
130 utils._check_uint64(value)
131 native_bt.field_bit_array_set_value_as_integer(self._ptr, value)
132
133 value_as_integer = property(
134 fget=_BitArrayFieldConst.value_as_integer.fget, fset=_value_as_integer
135 )
136
137
81447b5b 138@functools.total_ordering
9cbe0c59 139class _NumericFieldConst(_FieldConst):
81447b5b
PP
140 @staticmethod
141 def _extract_value(other):
9cbe0c59 142 if isinstance(other, _BoolFieldConst) or isinstance(other, bool):
a07f15cb 143 return bool(other)
81447b5b
PP
144
145 if isinstance(other, numbers.Integral):
146 return int(other)
147
148 if isinstance(other, numbers.Real):
149 return float(other)
150
151 if isinstance(other, numbers.Complex):
152 return complex(other)
153
61d96b89
FD
154 raise TypeError(
155 "'{}' object is not a number object".format(other.__class__.__name__)
156 )
81447b5b
PP
157
158 def __int__(self):
80d037bc 159 return int(self._value)
81447b5b
PP
160
161 def __float__(self):
80d037bc 162 return float(self._value)
81447b5b 163
dc78ca2f 164 def _repr(self):
e100fef0 165 return repr(self._value)
81447b5b
PP
166
167 def __lt__(self, other):
168 if not isinstance(other, numbers.Number):
61d96b89
FD
169 raise TypeError(
170 'unorderable types: {}() < {}()'.format(
171 self.__class__.__name__, other.__class__.__name__
172 )
173 )
81447b5b 174
5f953519 175 return self._value < self._extract_value(other)
81447b5b 176
80d037bc 177 def _spec_eq(self, other):
0bde7b52
PP
178 try:
179 return self._value == self._extract_value(other)
5760d571 180 except Exception:
0bde7b52 181 return False
81447b5b 182
04068900
FD
183 def __hash__(self):
184 return hash(self._value)
185
81447b5b 186 def __rmod__(self, other):
80d037bc 187 return self._extract_value(other) % self._value
81447b5b
PP
188
189 def __mod__(self, other):
80d037bc 190 return self._value % self._extract_value(other)
81447b5b
PP
191
192 def __rfloordiv__(self, other):
80d037bc 193 return self._extract_value(other) // self._value
81447b5b
PP
194
195 def __floordiv__(self, other):
80d037bc 196 return self._value // self._extract_value(other)
81447b5b
PP
197
198 def __round__(self, ndigits=None):
199 if ndigits is None:
80d037bc 200 return round(self._value)
81447b5b 201 else:
80d037bc 202 return round(self._value, ndigits)
81447b5b
PP
203
204 def __ceil__(self):
80d037bc 205 return math.ceil(self._value)
81447b5b
PP
206
207 def __floor__(self):
80d037bc 208 return math.floor(self._value)
81447b5b
PP
209
210 def __trunc__(self):
80d037bc 211 return int(self._value)
81447b5b
PP
212
213 def __abs__(self):
80d037bc 214 return abs(self._value)
81447b5b
PP
215
216 def __add__(self, other):
80d037bc 217 return self._value + self._extract_value(other)
81447b5b
PP
218
219 def __radd__(self, other):
220 return self.__add__(other)
221
222 def __neg__(self):
80d037bc 223 return -self._value
81447b5b
PP
224
225 def __pos__(self):
80d037bc 226 return +self._value
81447b5b
PP
227
228 def __mul__(self, other):
80d037bc 229 return self._value * self._extract_value(other)
81447b5b
PP
230
231 def __rmul__(self, other):
232 return self.__mul__(other)
233
234 def __truediv__(self, other):
80d037bc 235 return self._value / self._extract_value(other)
81447b5b
PP
236
237 def __rtruediv__(self, other):
80d037bc 238 return self._extract_value(other) / self._value
81447b5b
PP
239
240 def __pow__(self, exponent):
80d037bc 241 return self._value ** self._extract_value(exponent)
81447b5b
PP
242
243 def __rpow__(self, base):
80d037bc 244 return self._extract_value(base) ** self._value
81447b5b 245
81447b5b 246
9cbe0c59 247class _NumericField(_NumericFieldConst, _Field):
04068900
FD
248 def __hash__(self):
249 # Non const field are not hashable as their value may be modified
250 # without changing the underlying Python object.
251 raise TypeError('unhashable type: \'{}\''.format(self._NAME))
9cbe0c59
FD
252
253
254class _IntegralFieldConst(_NumericFieldConst, numbers.Integral):
81447b5b 255 def __lshift__(self, other):
80d037bc 256 return self._value << self._extract_value(other)
81447b5b
PP
257
258 def __rlshift__(self, other):
80d037bc 259 return self._extract_value(other) << self._value
81447b5b
PP
260
261 def __rshift__(self, other):
80d037bc 262 return self._value >> self._extract_value(other)
81447b5b
PP
263
264 def __rrshift__(self, other):
80d037bc 265 return self._extract_value(other) >> self._value
81447b5b
PP
266
267 def __and__(self, other):
80d037bc 268 return self._value & self._extract_value(other)
81447b5b
PP
269
270 def __rand__(self, other):
80d037bc 271 return self._extract_value(other) & self._value
81447b5b
PP
272
273 def __xor__(self, other):
80d037bc 274 return self._value ^ self._extract_value(other)
81447b5b
PP
275
276 def __rxor__(self, other):
80d037bc 277 return self._extract_value(other) ^ self._value
81447b5b
PP
278
279 def __or__(self, other):
80d037bc 280 return self._value | self._extract_value(other)
81447b5b
PP
281
282 def __ror__(self, other):
80d037bc 283 return self._extract_value(other) | self._value
81447b5b
PP
284
285 def __invert__(self):
80d037bc 286 return ~self._value
81447b5b 287
81447b5b 288
9cbe0c59
FD
289class _IntegralField(_IntegralFieldConst, _NumericField):
290 pass
291
292
293class _BoolFieldConst(_IntegralFieldConst, _FieldConst):
294 _NAME = 'Const boolean'
a07f15cb
PP
295
296 def __bool__(self):
297 return self._value
298
9cbe0c59
FD
299 @classmethod
300 def _value_to_bool(cls, value):
301 if isinstance(value, _BoolFieldConst):
a07f15cb
PP
302 value = value._value
303
304 if not isinstance(value, bool):
305 raise TypeError(
9cbe0c59 306 "'{}' object is not a 'bool', '_BoolFieldConst', or '_BoolField' object".format(
a07f15cb
PP
307 value.__class__
308 )
309 )
310
311 return value
312
313 @property
314 def _value(self):
315 return bool(native_bt.field_bool_get_value(self._ptr))
316
9cbe0c59
FD
317
318class _BoolField(_BoolFieldConst, _IntegralField, _Field):
319 _NAME = 'Boolean'
320
a07f15cb
PP
321 def _set_value(self, value):
322 value = self._value_to_bool(value)
323 native_bt.field_bool_set_value(self._ptr, value)
324
325 value = property(fset=_set_value)
326
327
9cbe0c59 328class _IntegerFieldConst(_IntegralFieldConst, _FieldConst):
81447b5b
PP
329 pass
330
331
9cbe0c59 332class _IntegerField(_IntegerFieldConst, _IntegralField, _Field):
cc80c640
FD
333 def _check_range(self, value):
334 if not (value >= self._lower_bound and value <= self._upper_bound):
335 raise ValueError(
336 "Value {} is outside valid range [{}, {}]".format(
337 value, self._lower_bound, self._upper_bound
338 )
339 )
9cbe0c59
FD
340
341
342class _UnsignedIntegerFieldConst(_IntegerFieldConst, _FieldConst):
343 _NAME = 'Const unsigned integer'
4470d3a6 344
9cbe0c59
FD
345 @classmethod
346 def _value_to_int(cls, value):
e2cf9726
PP
347 if not isinstance(value, numbers.Integral):
348 raise TypeError('expecting an integral number object')
81447b5b 349
cc80c640 350 return int(value)
81447b5b
PP
351
352 @property
80d037bc 353 def _value(self):
60bbfc7c 354 return native_bt.field_integer_unsigned_get_value(self._ptr)
81447b5b 355
9cbe0c59
FD
356
357class _UnsignedIntegerField(_UnsignedIntegerFieldConst, _IntegerField, _Field):
358 _NAME = 'Unsigned integer'
359
27d97a3f
SM
360 def _set_value(self, value):
361 value = self._value_to_int(value)
cc80c640
FD
362
363 self._check_range(value)
364
60bbfc7c 365 native_bt.field_integer_unsigned_set_value(self._ptr, value)
27d97a3f
SM
366
367 value = property(fset=_set_value)
368
cc80c640
FD
369 @property
370 def _lower_bound(self):
371 return 0
372
373 @property
374 def _upper_bound(self):
375 return (2 ** self.cls.field_value_range) - 1
376
27d97a3f 377
9cbe0c59
FD
378class _SignedIntegerFieldConst(_IntegerFieldConst, _FieldConst):
379 _NAME = 'Const signed integer'
4470d3a6 380
9cbe0c59
FD
381 @classmethod
382 def _value_to_int(cls, value):
e2cf9726
PP
383 if not isinstance(value, numbers.Integral):
384 raise TypeError('expecting an integral number object')
80d037bc 385
cc80c640 386 return int(value)
81447b5b 387
27d97a3f
SM
388 @property
389 def _value(self):
60bbfc7c 390 return native_bt.field_integer_signed_get_value(self._ptr)
27d97a3f 391
9cbe0c59
FD
392
393class _SignedIntegerField(_SignedIntegerFieldConst, _IntegerField, _Field):
394 _NAME = 'Signed integer'
395
80d037bc 396 def _set_value(self, value):
81447b5b 397 value = self._value_to_int(value)
cc80c640
FD
398
399 self._check_range(value)
400
60bbfc7c 401 native_bt.field_integer_signed_set_value(self._ptr, value)
81447b5b 402
80d037bc 403 value = property(fset=_set_value)
81447b5b 404
cc80c640
FD
405 @property
406 def _lower_bound(self):
407 return -1 * (2 ** (self.cls.field_value_range - 1))
408
409 @property
410 def _upper_bound(self):
411 return (2 ** (self.cls.field_value_range - 1)) - 1
412
5c8b3186 413
9cbe0c59
FD
414class _RealFieldConst(_NumericFieldConst, numbers.Real):
415 _NAME = 'Const real'
81447b5b 416
9cbe0c59
FD
417 @classmethod
418 def _value_to_float(cls, value):
81447b5b
PP
419 if not isinstance(value, numbers.Real):
420 raise TypeError("expecting a real number object")
421
422 return float(value)
423
76276a81
FD
424
425class _SinglePrecisionRealFieldConst(_RealFieldConst):
426 _NAME = 'Const single-precision real'
427
428 @property
429 def _value(self):
430 return native_bt.field_real_single_precision_get_value(self._ptr)
431
432
433class _DoublePrecisionRealFieldConst(_RealFieldConst):
434 _NAME = 'Const double-precision real'
435
81447b5b 436 @property
80d037bc 437 def _value(self):
76276a81 438 return native_bt.field_real_double_precision_get_value(self._ptr)
81447b5b 439
9cbe0c59
FD
440
441class _RealField(_RealFieldConst, _NumericField):
442 _NAME = 'Real'
443
76276a81
FD
444
445class _SinglePrecisionRealField(_SinglePrecisionRealFieldConst, _RealField):
446 _NAME = 'Single-precision real'
447
448 def _set_value(self, value):
449 value = self._value_to_float(value)
450 native_bt.field_real_single_precision_set_value(self._ptr, value)
451
452 value = property(fset=_set_value)
453
454
455class _DoublePrecisionRealField(_DoublePrecisionRealFieldConst, _RealField):
456 _NAME = 'Double-precision real'
457
80d037bc 458 def _set_value(self, value):
81447b5b 459 value = self._value_to_float(value)
76276a81 460 native_bt.field_real_double_precision_set_value(self._ptr, value)
81447b5b 461
80d037bc 462 value = property(fset=_set_value)
81447b5b 463
5c8b3186 464
9cbe0c59 465class _EnumerationFieldConst(_IntegerFieldConst):
4470d3a6
SM
466 def _repr(self):
467 return '{} ({})'.format(self._value, ', '.join(self.labels))
81447b5b
PP
468
469 @property
4470d3a6 470 def labels(self):
fb25b9e3 471 status, labels = self._get_mapping_labels(self._ptr)
61d96b89 472 utils._handle_func_status(status, "cannot get label for enumeration field")
81447b5b 473
4470d3a6
SM
474 assert labels is not None
475 return labels
81447b5b 476
a310d6bd 477
9cbe0c59
FD
478class _EnumerationField(_EnumerationFieldConst, _IntegerField):
479 pass
480
481
482class _UnsignedEnumerationFieldConst(
483 _EnumerationFieldConst, _UnsignedIntegerFieldConst
484):
485 _NAME = 'Const unsigned Enumeration'
61d96b89 486 _get_mapping_labels = staticmethod(
60bbfc7c 487 native_bt.field_enumeration_unsigned_get_mapping_labels
61d96b89 488 )
80d037bc 489
80d037bc 490
9cbe0c59
FD
491class _UnsignedEnumerationField(
492 _UnsignedEnumerationFieldConst, _EnumerationField, _UnsignedIntegerField
493):
494 _NAME = 'Unsigned enumeration'
495
496
497class _SignedEnumerationFieldConst(_EnumerationFieldConst, _SignedIntegerFieldConst):
498 _NAME = 'Const signed Enumeration'
61d96b89 499 _get_mapping_labels = staticmethod(
60bbfc7c 500 native_bt.field_enumeration_signed_get_mapping_labels
61d96b89 501 )
81447b5b
PP
502
503
9cbe0c59
FD
504class _SignedEnumerationField(
505 _SignedEnumerationFieldConst, _EnumerationField, _SignedIntegerField
506):
507 _NAME = 'Signed enumeration'
508
509
81447b5b 510@functools.total_ordering
9cbe0c59
FD
511class _StringFieldConst(_FieldConst):
512 _NAME = 'Const string'
81447b5b 513
9cbe0c59
FD
514 @classmethod
515 def _value_to_str(cls, value):
516 if isinstance(value, _StringFieldConst):
80d037bc 517 value = value._value
81447b5b
PP
518
519 if not isinstance(value, str):
520 raise TypeError("expecting a 'str' object")
521
522 return value
523
524 @property
80d037bc 525 def _value(self):
4470d3a6 526 return native_bt.field_string_get_value(self._ptr)
81447b5b 527
80d037bc 528 def _spec_eq(self, other):
81447b5b 529 try:
0bde7b52 530 return self._value == self._value_to_str(other)
5760d571 531 except Exception:
81447b5b
PP
532 return False
533
81447b5b 534 def __lt__(self, other):
80d037bc 535 return self._value < self._value_to_str(other)
81447b5b
PP
536
537 def __bool__(self):
80d037bc 538 return bool(self._value)
81447b5b 539
04068900
FD
540 def __hash__(self):
541 return hash(self._value)
542
dc78ca2f 543 def _repr(self):
89182b7e
JG
544 return repr(self._value)
545
81447b5b 546 def __str__(self):
4470d3a6 547 return str(self._value)
81447b5b
PP
548
549 def __getitem__(self, index):
80d037bc 550 return self._value[index]
81447b5b
PP
551
552 def __len__(self):
4470d3a6 553 return native_bt.field_string_get_length(self._ptr)
81447b5b 554
9cbe0c59
FD
555
556class _StringField(_StringFieldConst, _Field):
557 _NAME = 'String'
558
559 def _set_value(self, value):
560 value = self._value_to_str(value)
561 native_bt.field_string_set_value(self._ptr, value)
562
563 value = property(fset=_set_value)
564
81447b5b
PP
565 def __iadd__(self, value):
566 value = self._value_to_str(value)
fb25b9e3 567 status = native_bt.field_string_append(self._ptr, value)
61d96b89
FD
568 utils._handle_func_status(
569 status, "cannot append to string field object's value"
570 )
81447b5b
PP
571 return self
572
04068900
FD
573 def __hash__(self):
574 # Non const field are not hashable as their value may be modified
575 # without changing the underlying Python object.
576 raise TypeError('unhashable type: \'{}\''.format(self._NAME))
577
81447b5b 578
9cbe0c59 579class _ContainerFieldConst(_FieldConst):
81447b5b
PP
580 def __bool__(self):
581 return len(self) != 0
582
9cbe0c59
FD
583 def _count(self):
584 return len(self.cls)
585
81447b5b
PP
586 def __len__(self):
587 count = self._count()
4470d3a6 588 assert count >= 0
81447b5b
PP
589 return count
590
591 def __delitem__(self, index):
592 raise NotImplementedError
593
9cbe0c59
FD
594 def __setitem__(self, index, value):
595 raise TypeError(
596 '\'{}\' object does not support item assignment'.format(self.__class__)
597 )
81447b5b 598
81447b5b 599
9cbe0c59
FD
600class _ContainerField(_ContainerFieldConst, _Field):
601 pass
81447b5b 602
81447b5b 603
9cbe0c59
FD
604class _StructureFieldConst(_ContainerFieldConst, collections.abc.Mapping):
605 _NAME = 'Const structure'
606 _borrow_member_field_ptr_by_index = staticmethod(
607 native_bt.field_structure_borrow_member_field_by_index_const
608 )
609 _borrow_member_field_ptr_by_name = staticmethod(
610 native_bt.field_structure_borrow_member_field_by_name_const
611 )
612
613 def _count(self):
614 return len(self.cls)
81447b5b 615
81447b5b
PP
616 def __iter__(self):
617 # same name iterator
ffe40722 618 return iter(self.cls)
81447b5b 619
80d037bc 620 def _spec_eq(self, other):
0bde7b52
PP
621 if not isinstance(other, collections.abc.Mapping):
622 return False
81447b5b 623
0bde7b52
PP
624 if len(self) != len(other):
625 # early mismatch
626 return False
81447b5b 627
0bde7b52
PP
628 for self_key in self:
629 if self_key not in other:
630 return False
81447b5b 631
0bde7b52
PP
632 if self[self_key] != other[self_key]:
633 return False
80d037bc 634
0bde7b52 635 return True
81447b5b 636
dc78ca2f 637 def _repr(self):
797f4a78
JG
638 items = ['{}: {}'.format(repr(k), repr(v)) for k, v in self.items()]
639 return '{{{}}}'.format(', '.join(items))
640
4470d3a6
SM
641 def __getitem__(self, key):
642 utils._check_str(key)
9cbe0c59 643 field_ptr = self._borrow_member_field_ptr_by_name(self._ptr, key)
5c8b3186 644
4470d3a6
SM
645 if field_ptr is None:
646 raise KeyError(key)
81447b5b 647
9cbe0c59 648 return self._create_field_from_ptr(
61d96b89
FD
649 field_ptr, self._owner_ptr, self._owner_get_ref, self._owner_put_ref
650 )
f6a5e476 651
4470d3a6
SM
652 def member_at_index(self, index):
653 utils._check_uint64(index)
f6a5e476 654
4470d3a6
SM
655 if index >= len(self):
656 raise IndexError
9cbe0c59 657 field_ptr = self._borrow_member_field_ptr_by_index(self._ptr, index)
4470d3a6 658 assert field_ptr is not None
9cbe0c59 659 return self._create_field_from_ptr(
61d96b89
FD
660 field_ptr, self._owner_ptr, self._owner_get_ref, self._owner_put_ref
661 )
4470d3a6
SM
662
663
9cbe0c59
FD
664class _StructureField(
665 _StructureFieldConst, _ContainerField, collections.abc.MutableMapping
666):
667 _NAME = 'Structure'
668 _borrow_member_field_ptr_by_index = staticmethod(
669 native_bt.field_structure_borrow_member_field_by_index
670 )
671 _borrow_member_field_ptr_by_name = staticmethod(
672 native_bt.field_structure_borrow_member_field_by_name
673 )
674
675 def __setitem__(self, key, value):
676 # raises if key is somehow invalid
677 field = self[key]
678
679 # the field's property does the appropriate conversion or raises
680 # the appropriate exception
681 field.value = value
682
683 def _set_value(self, values):
684 try:
685 for key, value in values.items():
686 self[key].value = value
687 except Exception:
688 raise
689
690 value = property(fset=_set_value)
691
692
693class _OptionFieldConst(_FieldConst):
694 _NAME = 'Const option'
695 _borrow_field_ptr = staticmethod(native_bt.field_option_borrow_field_const)
84eba0d9
PP
696
697 @property
698 def field(self):
9cbe0c59 699 field_ptr = self._borrow_field_ptr(self._ptr)
84eba0d9
PP
700
701 if field_ptr is None:
702 return
703
9cbe0c59 704 return self._create_field_from_ptr(
84eba0d9
PP
705 field_ptr, self._owner_ptr, self._owner_get_ref, self._owner_put_ref
706 )
707
708 @property
709 def has_field(self):
710 return self.field is not None
711
84eba0d9
PP
712 def _spec_eq(self, other):
713 return _get_leaf_field(self) == other
714
715 def __bool__(self):
716 return self.has_field
717
718 def __str__(self):
719 return str(self.field)
720
721 def _repr(self):
722 return repr(self.field)
723
9cbe0c59
FD
724
725class _OptionField(_OptionFieldConst, _Field):
726 _NAME = 'Option'
727 _borrow_field_ptr = staticmethod(native_bt.field_option_borrow_field)
728
729 def _has_field(self, value):
730 utils._check_bool(value)
731 native_bt.field_option_set_has_field(self._ptr, value)
732
733 has_field = property(fget=_OptionFieldConst.has_field.fget, fset=_has_field)
734
84eba0d9
PP
735 def _set_value(self, value):
736 self.has_field = True
737 field = self.field
738 assert field is not None
739 field.value = value
740
741 value = property(fset=_set_value)
742
743
9cbe0c59
FD
744class _VariantFieldConst(_ContainerFieldConst, _FieldConst):
745 _NAME = 'Const variant'
746 _borrow_selected_option_field_ptr = staticmethod(
747 native_bt.field_variant_borrow_selected_option_field_const
748 )
81447b5b 749
7a4b69d3
FD
750 def _count(self):
751 return len(self.cls)
752
81447b5b 753 @property
4470d3a6
SM
754 def selected_option_index(self):
755 return native_bt.field_variant_get_selected_option_field_index(self._ptr)
81447b5b 756
4470d3a6
SM
757 @property
758 def selected_option(self):
100b6d91
SM
759 # TODO: Is there a way to check if the variant field has a selected_option,
760 # so we can raise an exception instead of hitting a pre-condition check?
761 # If there is something, that check should be added to selected_option_index too.
9cbe0c59 762 field_ptr = self._borrow_selected_option_field_ptr(self._ptr)
81447b5b 763
9cbe0c59 764 return self._create_field_from_ptr(
61d96b89
FD
765 field_ptr, self._owner_ptr, self._owner_get_ref, self._owner_put_ref
766 )
81447b5b 767
80d037bc 768 def _spec_eq(self, other):
0bde7b52 769 return _get_leaf_field(self) == other
f6a5e476
PP
770
771 def __bool__(self):
4470d3a6 772 raise NotImplementedError
81447b5b 773
dc78ca2f 774 def __str__(self):
4470d3a6 775 return str(self.selected_option)
dc78ca2f
JG
776
777 def _repr(self):
4470d3a6 778 return repr(self.selected_option)
80d037bc 779
9cbe0c59
FD
780
781class _VariantField(_VariantFieldConst, _ContainerField, _Field):
782 _NAME = 'Variant'
783 _borrow_selected_option_field_ptr = staticmethod(
784 native_bt.field_variant_borrow_selected_option_field
785 )
786
787 def _selected_option_index(self, index):
788 if index < 0 or index >= len(self):
789 raise IndexError('{} field object index is out of range'.format(self._NAME))
790
791 native_bt.field_variant_select_option_field_by_index(self._ptr, index)
792
793 selected_option_index = property(
794 fget=_VariantFieldConst.selected_option_index.fget, fset=_selected_option_index
795 )
796
80d037bc 797 def _set_value(self, value):
4470d3a6 798 self.selected_option.value = value
80d037bc
JG
799
800 value = property(fset=_set_value)
81447b5b 801
5c8b3186 802
9cbe0c59
FD
803class _ArrayFieldConst(_ContainerFieldConst, _FieldConst, collections.abc.Sequence):
804 _borrow_element_field_ptr_by_index = staticmethod(
805 native_bt.field_array_borrow_element_field_by_index_const
806 )
807
4470d3a6
SM
808 def _get_length(self):
809 return native_bt.field_array_get_length(self._ptr)
810
811 length = property(fget=_get_length)
812
81447b5b
PP
813 def __getitem__(self, index):
814 if not isinstance(index, numbers.Integral):
61d96b89
FD
815 raise TypeError(
816 "'{}' is not an integral number object: invalid index".format(
817 index.__class__.__name__
818 )
819 )
81447b5b
PP
820
821 index = int(index)
822
823 if index < 0 or index >= len(self):
824 raise IndexError('{} field object index is out of range'.format(self._NAME))
825
9cbe0c59 826 field_ptr = self._borrow_element_field_ptr_by_index(self._ptr, index)
61d96b89 827 assert field_ptr
9cbe0c59 828 return self._create_field_from_ptr(
61d96b89
FD
829 field_ptr, self._owner_ptr, self._owner_get_ref, self._owner_put_ref
830 )
81447b5b 831
81447b5b
PP
832 def insert(self, index, value):
833 raise NotImplementedError
834
80d037bc 835 def _spec_eq(self, other):
0bde7b52
PP
836 if not isinstance(other, collections.abc.Sequence):
837 return False
d5697082 838
0bde7b52
PP
839 if len(self) != len(other):
840 # early mismatch
80d037bc 841 return False
d5697082 842
0bde7b52
PP
843 for self_elem, other_elem in zip(self, other):
844 if self_elem != other_elem:
845 return False
846
847 return True
848
dc78ca2f 849 def _repr(self):
7e06e400
JG
850 return '[{}]'.format(', '.join([repr(v) for v in self]))
851
81447b5b 852
9cbe0c59
FD
853class _ArrayField(
854 _ArrayFieldConst, _ContainerField, _Field, collections.abc.MutableSequence
855):
856 _borrow_element_field_ptr_by_index = staticmethod(
857 native_bt.field_array_borrow_element_field_by_index
858 )
859
860 def __setitem__(self, index, value):
861 # raises if index is somehow invalid
862 field = self[index]
863
864 if not isinstance(field, (_NumericField, _StringField)):
865 raise TypeError('can only set the value of a number or string field')
866
867 # the field's property does the appropriate conversion or raises
868 # the appropriate exception
869 field.value = value
870
871
872class _StaticArrayFieldConst(_ArrayFieldConst, _FieldConst):
873 _NAME = 'Const static array'
81447b5b
PP
874
875 def _count(self):
4470d3a6 876 return native_bt.field_array_get_length(self._ptr)
81447b5b 877
9cbe0c59
FD
878
879class _StaticArrayField(_StaticArrayFieldConst, _ArrayField, _Field):
880 _NAME = 'Static array'
881
80d037bc
JG
882 def _set_value(self, values):
883 if len(self) != len(values):
e5e6a30a
SM
884 raise ValueError(
885 'expected length of value ({}) and array field ({}) to match'.format(
886 len(values), len(self)
887 )
888 )
80d037bc 889
4470d3a6
SM
890 for index, value in enumerate(values):
891 if value is not None:
892 self[index].value = value
80d037bc
JG
893
894 value = property(fset=_set_value)
895
81447b5b 896
9cbe0c59
FD
897class _DynamicArrayFieldConst(_ArrayFieldConst, _FieldConst):
898 _NAME = 'Const dynamic array'
81447b5b
PP
899
900 def _count(self):
4470d3a6 901 return self.length
81447b5b 902
9cbe0c59
FD
903
904class _DynamicArrayField(_DynamicArrayFieldConst, _ArrayField, _Field):
905 _NAME = 'Dynamic array'
906
4470d3a6
SM
907 def _set_length(self, length):
908 utils._check_uint64(length)
60bbfc7c 909 status = native_bt.field_array_dynamic_set_length(self._ptr, length)
fb25b9e3 910 utils._handle_func_status(status, "cannot set dynamic array length")
81447b5b 911
4470d3a6 912 length = property(fget=_ArrayField._get_length, fset=_set_length)
81447b5b 913
80d037bc 914 def _set_value(self, values):
4470d3a6
SM
915 if len(values) != self.length:
916 self.length = len(values)
80d037bc 917
4470d3a6
SM
918 for index, value in enumerate(values):
919 if value is not None:
920 self[index].value = value
80d037bc
JG
921
922 value = property(fset=_set_value)
81447b5b 923
5c8b3186 924
9cbe0c59
FD
925_TYPE_ID_TO_CONST_OBJ = {
926 native_bt.FIELD_CLASS_TYPE_BOOL: _BoolFieldConst,
927 native_bt.FIELD_CLASS_TYPE_BIT_ARRAY: _BitArrayFieldConst,
928 native_bt.FIELD_CLASS_TYPE_UNSIGNED_INTEGER: _UnsignedIntegerFieldConst,
929 native_bt.FIELD_CLASS_TYPE_SIGNED_INTEGER: _SignedIntegerFieldConst,
76276a81
FD
930 native_bt.FIELD_CLASS_TYPE_SINGLE_PRECISION_REAL: _SinglePrecisionRealFieldConst,
931 native_bt.FIELD_CLASS_TYPE_DOUBLE_PRECISION_REAL: _DoublePrecisionRealFieldConst,
9cbe0c59
FD
932 native_bt.FIELD_CLASS_TYPE_UNSIGNED_ENUMERATION: _UnsignedEnumerationFieldConst,
933 native_bt.FIELD_CLASS_TYPE_SIGNED_ENUMERATION: _SignedEnumerationFieldConst,
934 native_bt.FIELD_CLASS_TYPE_STRING: _StringFieldConst,
935 native_bt.FIELD_CLASS_TYPE_STRUCTURE: _StructureFieldConst,
936 native_bt.FIELD_CLASS_TYPE_STATIC_ARRAY: _StaticArrayFieldConst,
b8ddb4f0
PP
937 native_bt.FIELD_CLASS_TYPE_DYNAMIC_ARRAY_WITHOUT_LENGTH_FIELD: _DynamicArrayFieldConst,
938 native_bt.FIELD_CLASS_TYPE_DYNAMIC_ARRAY_WITH_LENGTH_FIELD: _DynamicArrayFieldConst,
467673c1
PP
939 native_bt.FIELD_CLASS_TYPE_OPTION_WITHOUT_SELECTOR: _OptionFieldConst,
940 native_bt.FIELD_CLASS_TYPE_OPTION_WITH_BOOL_SELECTOR: _OptionFieldConst,
941 native_bt.FIELD_CLASS_TYPE_OPTION_WITH_UNSIGNED_INTEGER_SELECTOR: _OptionFieldConst,
942 native_bt.FIELD_CLASS_TYPE_OPTION_WITH_SIGNED_INTEGER_SELECTOR: _OptionFieldConst,
9cbe0c59 943 native_bt.FIELD_CLASS_TYPE_VARIANT_WITHOUT_SELECTOR: _VariantFieldConst,
0822832b
PP
944 native_bt.FIELD_CLASS_TYPE_VARIANT_WITH_UNSIGNED_INTEGER_SELECTOR: _VariantFieldConst,
945 native_bt.FIELD_CLASS_TYPE_VARIANT_WITH_SIGNED_INTEGER_SELECTOR: _VariantFieldConst,
9cbe0c59
FD
946}
947
81447b5b 948_TYPE_ID_TO_OBJ = {
a07f15cb 949 native_bt.FIELD_CLASS_TYPE_BOOL: _BoolField,
6b29f2d4 950 native_bt.FIELD_CLASS_TYPE_BIT_ARRAY: _BitArrayField,
27d97a3f
SM
951 native_bt.FIELD_CLASS_TYPE_UNSIGNED_INTEGER: _UnsignedIntegerField,
952 native_bt.FIELD_CLASS_TYPE_SIGNED_INTEGER: _SignedIntegerField,
76276a81
FD
953 native_bt.FIELD_CLASS_TYPE_SINGLE_PRECISION_REAL: _SinglePrecisionRealField,
954 native_bt.FIELD_CLASS_TYPE_DOUBLE_PRECISION_REAL: _DoublePrecisionRealField,
4470d3a6
SM
955 native_bt.FIELD_CLASS_TYPE_UNSIGNED_ENUMERATION: _UnsignedEnumerationField,
956 native_bt.FIELD_CLASS_TYPE_SIGNED_ENUMERATION: _SignedEnumerationField,
27d97a3f
SM
957 native_bt.FIELD_CLASS_TYPE_STRING: _StringField,
958 native_bt.FIELD_CLASS_TYPE_STRUCTURE: _StructureField,
4470d3a6 959 native_bt.FIELD_CLASS_TYPE_STATIC_ARRAY: _StaticArrayField,
b8ddb4f0
PP
960 native_bt.FIELD_CLASS_TYPE_DYNAMIC_ARRAY_WITHOUT_LENGTH_FIELD: _DynamicArrayField,
961 native_bt.FIELD_CLASS_TYPE_DYNAMIC_ARRAY_WITH_LENGTH_FIELD: _DynamicArrayField,
467673c1
PP
962 native_bt.FIELD_CLASS_TYPE_OPTION_WITHOUT_SELECTOR: _OptionField,
963 native_bt.FIELD_CLASS_TYPE_OPTION_WITH_BOOL_SELECTOR: _OptionField,
964 native_bt.FIELD_CLASS_TYPE_OPTION_WITH_UNSIGNED_INTEGER_SELECTOR: _OptionField,
965 native_bt.FIELD_CLASS_TYPE_OPTION_WITH_SIGNED_INTEGER_SELECTOR: _OptionField,
02b61fe0 966 native_bt.FIELD_CLASS_TYPE_VARIANT_WITHOUT_SELECTOR: _VariantField,
0822832b
PP
967 native_bt.FIELD_CLASS_TYPE_VARIANT_WITH_UNSIGNED_INTEGER_SELECTOR: _VariantField,
968 native_bt.FIELD_CLASS_TYPE_VARIANT_WITH_SIGNED_INTEGER_SELECTOR: _VariantField,
81447b5b 969}
This page took 0.106537 seconds and 4 git commands to generate.