static <T extends AbstractType> DataExternalizer<T> externalizer(final DependencyContext context) {
    return new DataExternalizer<>() {
      @Override
      public void save(final @NotNull DataOutput out, final T value) {
        value.save(out);
      }

      @Override
      public T read(final @NotNull DataInput in) throws IOException {
        AbstractType elementType;
        int level = 0;

        loop:
        while (true) {
          final byte tag = in.readByte();
          switch (tag) {
            case PRIMITIVE_TYPE:
              elementType = context.getType(new PrimitiveType(in));
              break loop;

            case CLASS_TYPE:
              elementType = context.getType(new ClassType(in));
              break loop;

            case ARRAY_TYPE:
              level++;
              break;

            default :
              System.out.println("Unknown type with tag " + tag);
          }
        }

        for (int i = 0; i < level; i++) {
          elementType = context.getType(new ArrayType(elementType));
        }

        try {
          return (T)elementType;
        }
        catch (ClassCastException e) {
          throw new IOException("Expected a different data type: " + e.getMessage(), e);
        }
      }
    };
  }
static <T extends AbstractType> DataExternalizer<T> externalizer(final DependencyContext context)