docs: def assign_fields(self):
          """Assign a position & length to any fields which do not have one.
  
          Users should typically call this method after all field values have
          been assigned, otherwise fields may be fixed at an inadequate size.
          """
          # We must fix fields at every level of the hierarchy separately
          # (otherwise fields of children won't be allowed to overlap). Here we
          # do a breadth-first iteration over the hierarchy to fix fields with
          # given starting positions; then we do depth-first to fix other fields.
  
          # Assign all fields with a fixed starting position in breadth first,
          # top-down order. The breadth-first ensures that children's fixed
          # position fields must fit around the fixed position fields of their
          # parents.
          queue = [(self.fields, {})]
          while queue:
              node, field_values = queue.pop(0)
  
              # Assign all fields at this level whose position is fixed
              self._assign_fields(node.fields, field_values,
                                  assign_positions=False)
  
              # Breadth-first search through children
              for requirements, child in iteritems(node.children):
                  requirements = dict(requirements)
                  requirements.update(field_values)
                  queue.append((child, requirements))
  
          # Assign all fields with movable starting positions in leaf-first,
          # depth-first order.  The depth first ordering for variable position
          # fields ensures that parents don't allocate fields in positions which
          # would collide with fixed and variable position fields their children
          # have already allocated.
  
          def recurse_assign_fields(node=self.fields, field_values={}):
              # Assign fields of child nodes first (allowing them to allocate
              # bits independently)
              for requirements, child in iteritems(node.children):
                  child_field_values = dict(requirements)
                  child_field_values.update(field_values)
                  recurse_assign_fields(child, child_field_values)
  
              # Finally, assign all remaining fields at this level in the tree
              self._assign_fields(node.fields, field_values,
                                  assign_positions=True)
          recurse_assign_fields()