@Override
  public boolean readComplexField() throws IOException {

    Preconditions.checkState(currentLevel > 0);

    final ComplexTypeHelper complexTypeHelper = currentComplexTypeHelpers[currentLevel - 1];
    final Field complexField = complexTypeHelper.complexField;
    switch (complexField.complexCategory) {
    case LIST:
      {
        final ListComplexTypeHelper listHelper = (ListComplexTypeHelper) complexTypeHelper;
        final int fieldPosition = listHelper.fieldPosition;
        final int complexFieldEnd = listHelper.complexFieldEnd;

        // When data is prematurely ended the fieldPosition will be 1 more than the end.
        Preconditions.checkState(fieldPosition <= complexFieldEnd + 1);

        final int fieldEnd = parseComplexField(fieldPosition, complexFieldEnd, currentLevel);
        listHelper.fieldPosition = fieldEnd + 1;  // Move past separator.

        currentFieldStart = fieldPosition;
        currentFieldLength = fieldEnd - fieldPosition;

        return doReadField(listHelper.elementField);
      }
    case MAP:
      {
        final MapComplexTypeHelper mapHelper = (MapComplexTypeHelper) complexTypeHelper;
        final int fieldPosition = mapHelper.fieldPosition;
        final int complexFieldEnd = mapHelper.complexFieldEnd;

        // When data is prematurely ended the fieldPosition will be 1 more than the end.
        Preconditions.checkState(fieldPosition <= complexFieldEnd + 1);
  
        currentFieldStart = fieldPosition;

        final boolean isParentMap = isParentMap();
        if (isParentMap) {
          currentLevel++;
        }
        int fieldEnd;
        if (!mapHelper.fieldHaveParsedKey) {

          // Parse until key separator (currentLevel + 1).
          fieldEnd = parseComplexField(fieldPosition, complexFieldEnd, currentLevel + 1);

          mapHelper.fieldPosition = fieldEnd + 1;  // Move past key separator.

          currentFieldLength = fieldEnd - fieldPosition;

          mapHelper.fieldHaveParsedKey = true;
          final boolean result = doReadField(mapHelper.keyField);
          if (isParentMap) {
            currentLevel--;
          }
          return result;
        } else {

          // Parse until pair separator (currentLevel).
          fieldEnd = parseComplexField(fieldPosition, complexFieldEnd, currentLevel);

          mapHelper.fieldPosition = fieldEnd + 1;  // Move past pair separator.

          currentFieldLength = fieldEnd - fieldPosition;

          mapHelper.fieldHaveParsedKey = false;
          final boolean result = doReadField(mapHelper.valueField);
          if (isParentMap) {
            currentLevel--;
          }
          return result;
        }
      }
    case STRUCT:
      {
        final StructComplexTypeHelper structHelper = (StructComplexTypeHelper) complexTypeHelper;
        final int fieldPosition = structHelper.fieldPosition;
        final int complexFieldEnd = structHelper.complexFieldEnd;

        // When data is prematurely ended the fieldPosition will be 1 more than the end.
        Preconditions.checkState(fieldPosition <= complexFieldEnd + 1);

        currentFieldStart = fieldPosition;

        final int nextFieldIndex = structHelper.nextFieldIndex;
        final Field[] fields = structHelper.fields;
        final int fieldEnd;
        if (nextFieldIndex != fields.length - 1) {

          // Parse until field separator (currentLevel).
          fieldEnd = parseComplexField(fieldPosition, complexFieldEnd, currentLevel);

          structHelper.fieldPosition = fieldEnd + 1;  // Move past parent field separator.

          currentFieldLength = fieldEnd - fieldPosition;

          return doReadField(fields[structHelper.nextFieldIndex++]);
        } else {

          // Parse until field separator (currentLevel).
          fieldEnd = parseComplexField(fieldPosition, complexFieldEnd, currentLevel);
          currentFieldLength = fieldEnd - fieldPosition;

          structHelper.nextFieldIndex = 0;
          boolean result = doReadField(fields[fields.length - 1]);

          if (!isEscaped) {

            // No parsing necessary -- the end is the parent's end.
            structHelper.fieldPosition = complexFieldEnd + 1;  // Move past parent field separator.
            currentEscapeCount = 0;
          } else {
            // We must parse to get the escape count.
            parseComplexField(fieldPosition, complexFieldEnd, currentLevel - 1);
          }

          return result;
        }
      }
    case UNION:
      {
        final UnionComplexTypeHelper unionHelper = (UnionComplexTypeHelper) complexTypeHelper;
        final int fieldPosition = unionHelper.fieldPosition;
        final int complexFieldEnd = unionHelper.complexFieldEnd;

        // When data is prematurely ended the fieldPosition will be 1 more than the end.
        Preconditions.checkState(fieldPosition <= complexFieldEnd + 1);

        currentFieldStart = fieldPosition;

        final int fieldEnd;
        if (!unionHelper.fieldHaveParsedTag) {
          boolean isParentMap = isParentMap();
          if (isParentMap) {
            currentLevel++;
          }

          // Parse until union separator (currentLevel).
          fieldEnd = parseComplexField(fieldPosition, complexFieldEnd, currentLevel);

          unionHelper.fieldPosition = fieldEnd + 1;  // Move past union separator.

          currentFieldLength = fieldEnd - fieldPosition;

          unionHelper.fieldHaveParsedTag = true;
          boolean successful = doReadField(unionHelper.tagField);
          if (!successful) {
            throw new IOException("Null union tag");
          }
          unionHelper.fieldTag = currentInt;

          if (isParentMap) {
            currentLevel--;
          }
          return true;
        } else {

          if (!isEscaped) {

            // No parsing necessary -- the end is the parent's end.
            unionHelper.fieldPosition = complexFieldEnd + 1;  // Move past parent field separator.
            currentEscapeCount = 0;
          } else {
            // We must parse to get the escape count.
            fieldEnd = parseComplexField(fieldPosition, complexFieldEnd, currentLevel - 1);
          }

          currentFieldLength = complexFieldEnd - fieldPosition;

          unionHelper.fieldHaveParsedTag = false;
          return doReadField(unionHelper.fields[unionHelper.fieldTag]);
        }
      }
    default:
      throw new Error("Unexpected complex category " + complexField.complexCategory);
    }
  }
Parse the byte[] and fill each field.

This is an adapted version of the parse method in the LazyStruct class.
They should parse things the same way.
serde/src/java/org/apache/hadoop/hive/serde2/lazy/fast/LazySimpleDeserializeRead.java