docs: def handle_fields(definitions, fields, prefix, offset, multiplier):
    """
    Helper for handling naming and sizing of fields. It's terrible.
    """
    items = []
    for f in fields:
      if f.type_id == "array" and f.options['fill'].value in CONSTRUCT_CODE:
        prefix_name = '.'.join([prefix, f.identifier]) if prefix else f.identifier
        n_with_values = f.options['n_with_values'].value
        bitfields = f.options['fields'].value if n_with_values > 0 else None
        if 'size' in f.options:
          name = "%s[%s]" % (f.options['fill'].value, str(f.options['size'].value))
          size = field_sizes[f.options['fill'].value] * f.options['size'].value
          item = FieldItem(prefix_name, name, offset, size,
                           str(f.units), f.desc, n_with_values, bitfields)
          items.append(item)
          offset += size
        else:
          name = "%s[%s]" % (f.options['fill'].value, "N")
          multiplier = field_sizes[f.options['fill'].value]
          size = field_sizes[f.options['fill'].value] * 1
          item = FieldItem(prefix_name, name, offset, "N",
                           str(f.units), f.desc, n_with_values, bitfields)
          items.append(item)
          offset += size
      elif f.type_id == "string":
        prefix_name = '.'.join([prefix, f.identifier]) if prefix else f.identifier
        n_with_values = f.options['n_with_values'].value
        bitfields = f.options['fields'].value if n_with_values > 0 else None
        if 'size' in f.options:
          name = "string"
          size = field_sizes['u8'] * f.options['size'].value
          item = FieldItem(prefix_name, name, offset, size,
                           str(f.units), f.desc, n_with_values, bitfields)
          items.append(item)
          offset += size
        else:
          name = "string"
          size = field_sizes['u8']
          multiplier = 1
          item = FieldItem(prefix_name, name, offset, "N",
                           str(f.units), f.desc, n_with_values, bitfields)
          items.append(item)
          offset += size
      elif f.type_id == "array":
        name = f.options['fill'].value
        definition = next(d for d in definitions if name == d.identifier)
        prefix_name = '.'.join([prefix, f.identifier]) if prefix else f.identifier
        (new_items, new_offset, new_multiplier) \
          = handle_fields(definitions,
                          definition.fields,
                          prefix_name + "[N]",
                          offset,
                          multiplier)
        multiplier = new_offset - offset
        (newer_items, newer_offset, newer_multiplier) \
          = handle_fields(definitions,
                          definition.fields,
                          prefix_name + "[N]", offset,
                          multiplier)
        items += newer_items
        offset = newer_offset
      elif f.type_id not in CONSTRUCT_CODE:
        name = f.type_id
        definition = next(d for d in definitions if name == d.identifier)
        prefix_name = '.'.join([prefix, f.identifier]) if prefix else f.identifier
        (new_items, new_offset, new_multiplier) \
          = handle_fields(definitions,
                          definition.fields,
                          prefix_name,
                          offset,
                          multiplier)
        items += new_items
        offset = new_offset
        multiplier = new_multiplier
      else:
        size = field_sizes[f.type_id]
        name = f.type_id
        adj_offset = "%dN+%d" % (multiplier, offset) if multiplier else offset
        prefix_name = '.'.join([prefix, f.identifier]) if prefix else f.identifier
        n_with_values = f.options['n_with_values'].value
        bitfields = f.options['fields'].value if n_with_values > 0 else None
        item = FieldItem(prefix_name, name, adj_offset, size, str(f.units), f.desc, n_with_values, bitfields)
        items.append(item)
        offset += size
    return (items, offset, multiplier)