@Override
  public AbstractArrayDefinition createDefinition(
      @Nullable IDefinitionScope definitionScope, String fieldName, BitBuffer input)
      throws CTFException {
    IDefinition lenDef = null;

    if (definitionScope != null) {
      lenDef = definitionScope.lookupDefinition(getLengthName());
    }

    if (lenDef == null) {
      throw new CTFException("Sequence length field not found"); // $NON-NLS-1$
    }

    if (!(lenDef instanceof IntegerDefinition)) {
      throw new CTFException("Sequence length field not integer"); // $NON-NLS-1$
    }

    IntegerDefinition lengthDefinition = (IntegerDefinition) lenDef;

    if (lengthDefinition.getDeclaration().isSigned()) {
      throw new CTFException("Sequence length must not be signed"); // $NON-NLS-1$
    }

    long length = lengthDefinition.getValue();
    if ((length > Integer.MAX_VALUE)
        || (!input.canRead((int) length * fElemType.getMaximumSize()))) {
      throw new CTFException("Sequence length too long " + length); // $NON-NLS-1$
    }

    if (isAlignedBytes()) {
      // Don't create "useless" definitions
      byte[] data = new byte[(int) length];
      input.get(data);
      return new ByteArrayDefinition(this, definitionScope, fieldName, data);
    }
    Collection<String> collection = fPaths.get(fieldName);
    while (collection.size() < length) {
      fPaths.put(fieldName, fieldName + '[' + collection.size() + ']');
    }
    List<String> paths = (List<String>) fPaths.get(fieldName);
    Builder<Definition> definitions = new ImmutableList.Builder<>();
    for (int i = 0; i < length; i++) {
      /* We should not have inserted any null values */
      String elemName = checkNotNull(paths.get(i));
      definitions.add(fElemType.createDefinition(definitionScope, elemName, input));
    }
    List<Definition> list = checkNotNull(definitions.build());
    return new ArrayDefinition(this, definitionScope, fieldName, list);
  }
 @Override
 public int hashCode() {
   final int prime = 31;
   int result = 1;
   result = prime * result + fElemType.hashCode();
   result = prime * result + fLengthName.hashCode();
   return result;
 }
 @Override
 public boolean isBinaryEquivalent(@Nullable IDeclaration obj) {
   if (this == obj) {
     return true;
   }
   if (obj == null) {
     return false;
   }
   if (getClass() != obj.getClass()) {
     return false;
   }
   SequenceDeclaration other = (SequenceDeclaration) obj;
   if (!fElemType.isBinaryEquivalent(other.fElemType)) {
     return false;
   }
   if (!fLengthName.equals(other.fLengthName)) {
     return false;
   }
   return true;
 }