|
- #
- # This file is part of usb-protocol.
- #
-
-
- from collections import defaultdict
-
- from . import ConstructEmitter
-
- class ComplexDescriptorEmitter(ConstructEmitter):
- """ Base class for emitting complex descriptors, which contain nested subordinates. """
-
- # Base classes should override this.
- DESCRIPTOR_FORMAT = None
-
- def __init__(self, collection=None):
- """
- Parameters:
- collection -- If this descriptor belongs to a collection, it should be
- provided here. Using a collection object allows e.g. automatic
- assignment of string descriptor indices.
- """
-
- self._collection = collection
-
- # Always create a basic ConstructEmitter from the given format.
- super().__init__(self.DESCRIPTOR_FORMAT)
-
- # Store a list of subordinate descriptors, and a count of
- # subordinate descriptor types.
- self._subordinates = []
- self._type_counts = defaultdict(int)
-
-
- def add_subordinate_descriptor(self, subordinate):
- """ Adds a subordinate descriptor to the relevant descriptor.
-
- Parameter:
- subordinate -- The subordinate descriptor to add; can be an emitter,
- or a bytes-like object.
- """
-
- if hasattr(subordinate, 'emit'):
- subordinate = subordinate.emit()
- else:
- subordinate = bytes(subordinate)
-
- # The second byte of a given descriptor is always its type number.
- # Count this descriptor type...
- subordinate_type = subordinate[1]
-
- self._type_counts[subordinate_type] += 1
-
- # ... and add the relevant bytes to our list of subordinates.
- self._subordinates.append(subordinate)
-
-
- def _pre_emit(self):
- """ Performs any manipulations needed on this object before emission. """
- pass
-
-
- def emit(self, include_subordinates=True):
- """ Emit our descriptor.
-
- Parameters:
- include_subordinates -- If true or not provided, any subordinate descriptors will be included.
- """
-
- # Run any pre-emit hook code before we perform our emission...
- self._pre_emit()
-
- # Start with our core descriptor...
- result = bytearray()
- result.extend(super().emit())
-
- # ... and if descired, add our subordinates...
- for sub in self._subordinates:
- result.extend(sub)
-
- return bytes(result)
-
|